diff --git a/README.md b/README.md index a0131583597..e50407eaaaa 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 64 lints included in this crate: +There are 66 lints included in this crate: name | default | meaning -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ @@ -68,6 +68,8 @@ 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 +[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 [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 8bf199bff47..a3657460fe9 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::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 new file mode 100644 index 00000000000..b1d38df7311 --- /dev/null +++ b/src/needless_features.rs @@ -0,0 +1,53 @@ +//! 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; + +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" +} + +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"]) +} diff --git a/src/utils.rs b/src/utils.rs index caf77332b62..80b8c88361a 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 new file mode 100644 index 00000000000..dee2a19d5d0 --- /dev/null +++ b/tests/compile-fail/needless_features.rs @@ -0,0 +1,29 @@ +#![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 [..] +} + +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(); +}