[`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
## Lints
-There are 178 lints included in this crate:
+There are 179 lints included in this crate:
name | default | triggers on
-----------------------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------
[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
pub mod print;
pub mod ptr;
pub mod ranges;
+pub mod reference;
pub mod regex;
pub mod returns;
pub mod serde;
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,
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,
--- /dev/null
+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, "_")));
+ });
+ }
+ }
+ }
+}
#![deny(no_effect, unnecessary_operation)]
#![allow(dead_code)]
#![allow(path_statements)]
+#![allow(deref_addrof)]
#![feature(untagged_unions)]
struct Unit;
--- /dev/null
+#![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
+ }
+}