Skip to content

Commit d61c7fc

Browse files
authored
Merge pull request #1355 from philipturnbull/deref-addrof
Lint usage of `*&` and `*&mut`
2 parents f8349e1 + 0ee6128 commit d61c7fc

File tree

7 files changed

+151
-1
lines changed

7 files changed

+151
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,7 @@ All notable changes to this project will be documented in this file.
263263
[`crosspointer_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#crosspointer_transmute
264264
[`cyclomatic_complexity`]: https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity
265265
[`deprecated_semver`]: https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver
266+
[`deref_addrof`]: https://github.com/Manishearth/rust-clippy/wiki#deref_addrof
266267
[`derive_hash_xor_eq`]: https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq
267268
[`diverging_sub_expression`]: https://github.com/Manishearth/rust-clippy/wiki#diverging_sub_expression
268269
[`doc_markdown`]: https://github.com/Manishearth/rust-clippy/wiki#doc_markdown

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ transparently:
172172

173173
## Lints
174174

175-
There are 178 lints included in this crate:
175+
There are 179 lints included in this crate:
176176

177177
name | default | triggers on
178178
-----------------------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------
@@ -204,6 +204,7 @@ name
204204
[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
205205
[cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | functions that should be split up into multiple functions
206206
[deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | use of `#[deprecated(since = "x")]` where x is not semver
207+
[deref_addrof](https://github.com/Manishearth/rust-clippy/wiki#deref_addrof) | warn | use of `*&` or `*&mut` in an expression
207208
[derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly
208209
[diverging_sub_expression](https://github.com/Manishearth/rust-clippy/wiki#diverging_sub_expression) | warn | whether an expression contains a diverging sub expression
209210
[doc_markdown](https://github.com/Manishearth/rust-clippy/wiki#doc_markdown) | warn | presence of `_`, `::` or camel-case outside backticks in documentation

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ pub mod precedence;
116116
pub mod print;
117117
pub mod ptr;
118118
pub mod ranges;
119+
pub mod reference;
119120
pub mod regex;
120121
pub mod returns;
121122
pub mod serde;
@@ -267,6 +268,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
267268
reg.register_late_lint_pass(box ok_if_let::Pass);
268269
reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass);
269270
reg.register_late_lint_pass(box partialeq_ne_impl::Pass);
271+
reg.register_early_lint_pass(box reference::Pass);
270272

271273
reg.register_lint_group("clippy_restrictions", vec![
272274
arithmetic::FLOAT_ARITHMETIC,
@@ -432,6 +434,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
432434
ptr::PTR_ARG,
433435
ranges::RANGE_STEP_BY_ZERO,
434436
ranges::RANGE_ZIP_WITH_LEN,
437+
reference::DEREF_ADDROF,
435438
regex::INVALID_REGEX,
436439
regex::REGEX_MACRO,
437440
regex::TRIVIAL_REGEX,

clippy_lints/src/reference.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use syntax::ast::{Expr,ExprKind,UnOp};
2+
use rustc::lint::*;
3+
use utils::{span_lint_and_then, snippet};
4+
5+
/// **What it does:** Checks for usage of `*&` and `*&mut` in expressions.
6+
///
7+
/// **Why is this bad?** Immediately dereferencing a reference is no-op and
8+
/// makes the code less clear.
9+
///
10+
/// **Known problems:** Multiple dereference/addrof pairs are not handled so
11+
/// the suggested fix for `x = **&&y` is `x = *&y`, which is still incorrect.
12+
///
13+
/// **Example:**
14+
/// ```rust
15+
/// let a = f(*&mut b);
16+
/// let c = *&d;
17+
/// ```
18+
declare_lint! {
19+
pub DEREF_ADDROF,
20+
Warn,
21+
"use of `*&` or `*&mut` in an expression"
22+
}
23+
24+
pub struct Pass;
25+
26+
impl LintPass for Pass {
27+
fn get_lints(&self) -> LintArray {
28+
lint_array!(DEREF_ADDROF)
29+
}
30+
}
31+
32+
fn without_parens(mut e: &Expr) -> &Expr {
33+
while let ExprKind::Paren(ref child_e) = e.node {
34+
e = child_e;
35+
}
36+
e
37+
}
38+
39+
impl EarlyLintPass for Pass {
40+
fn check_expr(&mut self, cx: &EarlyContext, e: &Expr) {
41+
if let ExprKind::Unary(UnOp::Deref, ref deref_target) = e.node {
42+
if let ExprKind::AddrOf(_, ref addrof_target) = without_parens(deref_target).node {
43+
span_lint_and_then(
44+
cx,
45+
DEREF_ADDROF,
46+
e.span,
47+
"immediately dereferencing a reference",
48+
|db| {
49+
db.span_suggestion(e.span, "try this",
50+
format!("{}", snippet(cx, addrof_target.span, "_")));
51+
});
52+
}
53+
}
54+
}
55+
}

tests/compile-fail/formatting.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#![allow(unused_variables)]
66
#![allow(unused_assignments)]
77
#![allow(if_same_then_else)]
8+
#![allow(deref_addrof)]
89

910
fn foo() -> bool { true }
1011

tests/compile-fail/no_effect.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#![deny(no_effect, unnecessary_operation)]
55
#![allow(dead_code)]
66
#![allow(path_statements)]
7+
#![allow(deref_addrof)]
78
#![feature(untagged_unions)]
89

910
struct Unit;

tests/compile-fail/reference.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
#![feature(plugin)]
2+
#![plugin(clippy)]
3+
4+
fn get_number() -> usize {
5+
10
6+
}
7+
8+
fn get_reference(n : &usize) -> &usize {
9+
n
10+
}
11+
12+
#[allow(many_single_char_names)]
13+
#[allow(unused_variables)]
14+
#[deny(deref_addrof)]
15+
fn main() {
16+
let a = 10;
17+
let aref = &a;
18+
19+
let b = *&a;
20+
//~^ERROR immediately dereferencing a reference
21+
//~|HELP try this
22+
//~|SUGGESTION let b = a;
23+
24+
let b = *&get_number();
25+
//~^ERROR immediately dereferencing a reference
26+
//~|HELP try this
27+
//~|SUGGESTION let b = get_number();
28+
29+
let b = *get_reference(&a);
30+
31+
let bytes : Vec<usize> = vec![1, 2, 3, 4];
32+
let b = *&bytes[1..2][0];
33+
//~^ERROR immediately dereferencing a reference
34+
//~|HELP try this
35+
//~|SUGGESTION let b = bytes[1..2][0];
36+
37+
//This produces a suggestion of 'let b = (a);' which
38+
//will trigger the 'unused_parens' lint
39+
let b = *&(a);
40+
//~^ERROR immediately dereferencing a reference
41+
//~|HELP try this
42+
//~|SUGGESTION let b = (a)
43+
44+
let b = *(&a);
45+
//~^ERROR immediately dereferencing a reference
46+
//~|HELP try this
47+
//~|SUGGESTION let b = a;
48+
49+
let b = *((&a));
50+
//~^ERROR immediately dereferencing a reference
51+
//~|HELP try this
52+
//~|SUGGESTION let b = a
53+
54+
let b = *&&a;
55+
//~^ERROR immediately dereferencing a reference
56+
//~|HELP try this
57+
//~|SUGGESTION let b = &a;
58+
59+
let b = **&aref;
60+
//~^ERROR immediately dereferencing a reference
61+
//~|HELP try this
62+
//~|SUGGESTION let b = *aref;
63+
64+
//This produces a suggestion of 'let b = *&a;' which
65+
//will trigger the 'deref_addrof' lint again
66+
let b = **&&a;
67+
//~^ERROR immediately dereferencing a reference
68+
//~|HELP try this
69+
//~|SUGGESTION let b = *&a;
70+
71+
{
72+
let mut x = 10;
73+
let y = *&mut x;
74+
//~^ERROR immediately dereferencing a reference
75+
//~|HELP try this
76+
//~|SUGGESTION let y = x;
77+
}
78+
79+
{
80+
//This produces a suggestion of 'let y = *&mut x' which
81+
//will trigger the 'deref_addrof' lint again
82+
let mut x = 10;
83+
let y = **&mut &mut x;
84+
//~^ERROR immediately dereferencing a reference
85+
//~|HELP try this
86+
//~|SUGGESTION let y = *&mut x;
87+
}
88+
}

0 commit comments

Comments
 (0)