From: Phil Turnbull Date: Tue, 22 Nov 2016 18:22:37 +0000 (-0500) Subject: Lint usage of `*&` and `*&mut` X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=a9f5b90f0f4994d6e11a7f75707f2010134a08fa;p=rust.git Lint usage of `*&` and `*&mut` fixes #1316 --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 14bf8ba1609..8c4c3b2eb8a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -248,6 +248,7 @@ All notable changes to this project will be documented in this file. [`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 diff --git a/README.md b/README.md index db291adefaf..b2d0c498f74 100644 --- a/README.md +++ b/README.md @@ -182,7 +182,7 @@ You can check out this great service at [clippy.bashy.io](https://clippy.bashy.i ## Lints -There are 178 lints included in this crate: +There are 179 lints included in this crate: name | default | triggers on -----------------------------------------------------------------------------------------------------------------------|---------|---------------------------------------------------------------------------------------------------------------------------------- @@ -214,6 +214,7 @@ name [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 diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index a90f121fe79..508ef023b80 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -115,6 +115,7 @@ macro_rules! declare_restriction_lint { pub mod print; pub mod ptr; pub mod ranges; +pub mod reference; pub mod regex; pub mod returns; pub mod serde; @@ -266,6 +267,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { 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); + reg.register_late_lint_pass(box reference::Pass); reg.register_lint_group("clippy_restrictions", vec![ arithmetic::FLOAT_ARITHMETIC, @@ -431,6 +433,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) { ptr::PTR_ARG, ranges::RANGE_STEP_BY_ZERO, ranges::RANGE_ZIP_WITH_LEN, + reference::DEREF_ADDROF, regex::INVALID_REGEX, regex::REGEX_MACRO, regex::TRIVIAL_REGEX, diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs new file mode 100644 index 00000000000..97ee9b2a577 --- /dev/null +++ b/clippy_lints/src/reference.rs @@ -0,0 +1,48 @@ +use rustc::hir::*; +use rustc::lint::*; +use utils::{span_lint_and_then, snippet}; + +/// **What it does:** Checks for usage of `*&` and `*&mut` in expressions. +/// +/// **Why is this bad?** Immediately dereferencing a reference is no-op and +/// makes the code less clear. +/// +/// **Known problems:** Multiple dereference/addrof pairs are not handled so +/// the suggested fix for `x = **&&y` is `x = *&y`, which is still incorrect. +/// +/// **Example:** +/// ```rust +/// let a = f(*&mut b); +/// let c = *&d; +/// ``` +declare_lint! { + pub DEREF_ADDROF, + Warn, + "use of `*&` or `*&mut` in an expression" +} + +pub struct Pass; + +impl LintPass for Pass { + fn get_lints(&self) -> LintArray { + lint_array!(DEREF_ADDROF) + } +} + +impl LateLintPass for Pass { + fn check_expr(&mut self, cx: &LateContext, e: &Expr) { + if let ExprUnary(UnDeref, ref deref_target) = e.node { + if let ExprAddrOf(_, ref addrof_target) = deref_target.node { + span_lint_and_then( + cx, + DEREF_ADDROF, + e.span, + "immediately dereferencing a reference", + |db| { + db.span_suggestion(e.span, "try this", + format!("{}", snippet(cx, addrof_target.span, "_"))); + }); + } + } + } +} diff --git a/tests/compile-fail/no_effect.rs b/tests/compile-fail/no_effect.rs index 6616f7bdc86..30a66a715f2 100644 --- a/tests/compile-fail/no_effect.rs +++ b/tests/compile-fail/no_effect.rs @@ -4,6 +4,7 @@ #![deny(no_effect, unnecessary_operation)] #![allow(dead_code)] #![allow(path_statements)] +#![allow(deref_addrof)] #![feature(untagged_unions)] struct Unit; diff --git a/tests/compile-fail/reference.rs b/tests/compile-fail/reference.rs new file mode 100644 index 00000000000..7a113ad5255 --- /dev/null +++ b/tests/compile-fail/reference.rs @@ -0,0 +1,74 @@ +#![feature(plugin)] +#![plugin(clippy)] + +fn get_number() -> usize { + 10 +} + +fn get_reference(n : &usize) -> &usize { + n +} + +#[allow(many_single_char_names)] +#[allow(unused_variables)] +#[deny(deref_addrof)] +fn main() { + let a = 10; + let aref = &a; + + let b = *&a; + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION a + + let b = *&get_number(); + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION get_number() + + let b = *get_reference(&a); + + let bytes : Vec = vec![1, 2, 3, 4]; + let b = *&bytes[1..2][0]; + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION bytes[1..2][0] + + let b = *(&a); + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION a + + let b = *&&a; + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION &a + + let b = **&aref; + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION aref + + //This produces a suggestion of 'let b = *&a;' which is still incorrect + let b = **&&a; + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION a + + { + let mut x = 10; + let y = *&mut x; + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION x + } + + { + //This produces a suggestion of 'let y = *&mut x' which is still incorrect + let mut x = 10; + let y = **&mut &mut x; + //~^ERROR immediately dereferencing a reference + //~|HELP try this + //~|SUGGESTION x + } +}