From 1bd023d3e01857b6fff86efb8da7159c84d0be5d Mon Sep 17 00:00:00 2001 From: Florian Gilcher Date: Thu, 15 Oct 2015 11:13:01 +0200 Subject: [PATCH 1/3] 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(); +} From 39e93d572b4fa85a71bbe04a2a1c15bcb445e26c Mon Sep 17 00:00:00 2001 From: Florian Gilcher Date: Thu, 15 Oct 2015 12:53:21 +0200 Subject: [PATCH 2/3] 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>`, 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, From 80639164770bd5755443b52073d358c7496a030a Mon Sep 17 00:00:00 2001 From: Florian Gilcher Date: Sat, 17 Oct 2015 20:16:54 +0200 Subject: [PATCH 3/3] 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"]) +} 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(); }