]> git.lizzy.rs Git - rust.git/commitdiff
Lint usage of `*&` and `*&mut`
authorPhil Turnbull <philip.turnbull@gmail.com>
Tue, 22 Nov 2016 18:22:37 +0000 (13:22 -0500)
committerPhil Turnbull <philip.turnbull@gmail.com>
Wed, 23 Nov 2016 02:06:20 +0000 (21:06 -0500)
fixes #1316

CHANGELOG.md
README.md
clippy_lints/src/lib.rs
clippy_lints/src/reference.rs [new file with mode: 0644]
tests/compile-fail/no_effect.rs
tests/compile-fail/reference.rs [new file with mode: 0644]

index 14bf8ba16090e2c68549f62a49d8631e6b67d737..8c4c3b2eb8a5649951a72bb7d667477cc6b08164 100644 (file)
@@ -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
index db291adefaf3d3a8c8c848f3132fbe641f6a83d8..b2d0c498f749ece0432cc3385359d340940fd7e0 100644 (file)
--- 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
index a90f121fe79ac034c8b4d24d71bf10ac9ceb36a0..508ef023b80f6a780e0a6690e218446a990c63ea 100644 (file)
@@ -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 (file)
index 0000000..97ee9b2
--- /dev/null
@@ -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, "_")));
+                    });
+            }
+        }
+    }
+}
index 6616f7bdc86c03a4ee2a0f95fdc2521056768068..30a66a715f2000ed5d1650b77dc66a449ff1887d 100644 (file)
@@ -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 (file)
index 0000000..7a113ad
--- /dev/null
@@ -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<usize> = 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
+    }
+}