Skip to content

Commit a9f5b90

Browse files
Lint usage of *& and *&mut
fixes #1316
1 parent 530083c commit a9f5b90

File tree

6 files changed

+129
-1
lines changed

6 files changed

+129
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,7 @@ All notable changes to this project will be documented in this file.
248248
[`crosspointer_transmute`]: https://github.com/Manishearth/rust-clippy/wiki#crosspointer_transmute
249249
[`cyclomatic_complexity`]: https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity
250250
[`deprecated_semver`]: https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver
251+
[`deref_addrof`]: https://github.com/Manishearth/rust-clippy/wiki#deref_addrof
251252
[`derive_hash_xor_eq`]: https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq
252253
[`diverging_sub_expression`]: https://github.com/Manishearth/rust-clippy/wiki#diverging_sub_expression
253254
[`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
@@ -182,7 +182,7 @@ You can check out this great service at [clippy.bashy.io](https://clippy.bashy.i
182182

183183
## Lints
184184

185-
There are 178 lints included in this crate:
185+
There are 179 lints included in this crate:
186186

187187
name | default | triggers on
188188
-----------------------------------------------------------------------------------------------------------------------|---------|----------------------------------------------------------------------------------------------------------------------------------
@@ -214,6 +214,7 @@ name
214214
[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
215215
[cyclomatic_complexity](https://github.com/Manishearth/rust-clippy/wiki#cyclomatic_complexity) | warn | functions that should be split up into multiple functions
216216
[deprecated_semver](https://github.com/Manishearth/rust-clippy/wiki#deprecated_semver) | warn | use of `#[deprecated(since = "x")]` where x is not semver
217+
[deref_addrof](https://github.com/Manishearth/rust-clippy/wiki#deref_addrof) | warn | use of `*&` or `*&mut` in an expression
217218
[derive_hash_xor_eq](https://github.com/Manishearth/rust-clippy/wiki#derive_hash_xor_eq) | warn | deriving `Hash` but implementing `PartialEq` explicitly
218219
[diverging_sub_expression](https://github.com/Manishearth/rust-clippy/wiki#diverging_sub_expression) | warn | whether an expression contains a diverging sub expression
219220
[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
@@ -115,6 +115,7 @@ pub mod precedence;
115115
pub mod print;
116116
pub mod ptr;
117117
pub mod ranges;
118+
pub mod reference;
118119
pub mod regex;
119120
pub mod returns;
120121
pub mod serde;
@@ -266,6 +267,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
266267
reg.register_late_lint_pass(box ok_if_let::Pass);
267268
reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass);
268269
reg.register_late_lint_pass(box partialeq_ne_impl::Pass);
270+
reg.register_late_lint_pass(box reference::Pass);
269271

270272
reg.register_lint_group("clippy_restrictions", vec![
271273
arithmetic::FLOAT_ARITHMETIC,
@@ -431,6 +433,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
431433
ptr::PTR_ARG,
432434
ranges::RANGE_STEP_BY_ZERO,
433435
ranges::RANGE_ZIP_WITH_LEN,
436+
reference::DEREF_ADDROF,
434437
regex::INVALID_REGEX,
435438
regex::REGEX_MACRO,
436439
regex::TRIVIAL_REGEX,

clippy_lints/src/reference.rs

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
use rustc::hir::*;
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+
impl LateLintPass for Pass {
33+
fn check_expr(&mut self, cx: &LateContext, e: &Expr) {
34+
if let ExprUnary(UnDeref, ref deref_target) = e.node {
35+
if let ExprAddrOf(_, ref addrof_target) = deref_target.node {
36+
span_lint_and_then(
37+
cx,
38+
DEREF_ADDROF,
39+
e.span,
40+
"immediately dereferencing a reference",
41+
|db| {
42+
db.span_suggestion(e.span, "try this",
43+
format!("{}", snippet(cx, addrof_target.span, "_")));
44+
});
45+
}
46+
}
47+
}
48+
}

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: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
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 a
23+
24+
let b = *&get_number();
25+
//~^ERROR immediately dereferencing a reference
26+
//~|HELP try this
27+
//~|SUGGESTION 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 bytes[1..2][0]
36+
37+
let b = *(&a);
38+
//~^ERROR immediately dereferencing a reference
39+
//~|HELP try this
40+
//~|SUGGESTION a
41+
42+
let b = *&&a;
43+
//~^ERROR immediately dereferencing a reference
44+
//~|HELP try this
45+
//~|SUGGESTION &a
46+
47+
let b = **&aref;
48+
//~^ERROR immediately dereferencing a reference
49+
//~|HELP try this
50+
//~|SUGGESTION aref
51+
52+
//This produces a suggestion of 'let b = *&a;' which is still incorrect
53+
let b = **&&a;
54+
//~^ERROR immediately dereferencing a reference
55+
//~|HELP try this
56+
//~|SUGGESTION a
57+
58+
{
59+
let mut x = 10;
60+
let y = *&mut x;
61+
//~^ERROR immediately dereferencing a reference
62+
//~|HELP try this
63+
//~|SUGGESTION x
64+
}
65+
66+
{
67+
//This produces a suggestion of 'let y = *&mut x' which is still incorrect
68+
let mut x = 10;
69+
let y = **&mut &mut x;
70+
//~^ERROR immediately dereferencing a reference
71+
//~|HELP try this
72+
//~|SUGGESTION x
73+
}
74+
}

0 commit comments

Comments
 (0)