Skip to content

Commit 0d1e06d

Browse files
authored
Merge pull request #2808 from Aaronepower/master
Added lint for unnecessary references.
2 parents b979f62 + 8b67917 commit 0d1e06d

File tree

4 files changed

+78
-0
lines changed

4 files changed

+78
-0
lines changed

clippy_lints/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
388388
reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass);
389389
reg.register_late_lint_pass(box partialeq_ne_impl::Pass);
390390
reg.register_early_lint_pass(box reference::Pass);
391+
reg.register_early_lint_pass(box reference::DerefPass);
391392
reg.register_early_lint_pass(box double_parens::DoubleParens);
392393
reg.register_late_lint_pass(box unused_io_amount::UnusedIoAmount);
393394
reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold));
@@ -809,6 +810,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
809810
precedence::PRECEDENCE,
810811
ranges::RANGE_ZIP_WITH_LEN,
811812
reference::DEREF_ADDROF,
813+
reference::REF_IN_DEREF,
812814
swap::MANUAL_SWAP,
813815
temporary_assignment::TEMPORARY_ASSIGNMENT,
814816
transmute::CROSSPOINTER_TRANSMUTE,

clippy_lints/src/reference.rs

+50
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,53 @@ impl EarlyLintPass for Pass {
5454
}
5555
}
5656
}
57+
58+
/// **What it does:** Checks for references in expressions that use
59+
/// auto dereference.
60+
///
61+
/// **Why is this bad?** The reference is a no-op and is automatically
62+
/// dereferenced by the compiler and makes the code less clear.
63+
///
64+
/// **Example:**
65+
/// ```rust
66+
/// struct Point(u32, u32);
67+
/// let point = Foo(30, 20);
68+
/// let x = (&point).x;
69+
/// ```
70+
declare_clippy_lint! {
71+
pub REF_IN_DEREF,
72+
complexity,
73+
"Use of reference in auto dereference expression."
74+
}
75+
76+
pub struct DerefPass;
77+
78+
impl LintPass for DerefPass {
79+
fn get_lints(&self) -> LintArray {
80+
lint_array!(REF_IN_DEREF)
81+
}
82+
}
83+
84+
impl EarlyLintPass for DerefPass {
85+
fn check_expr(&mut self, cx: &EarlyContext, e: &Expr) {
86+
if_chain! {
87+
if let ExprKind::Field(ref object, ref field_name) = e.node;
88+
if let ExprKind::Paren(ref parened) = object.node;
89+
if let ExprKind::AddrOf(_, ref inner) = parened.node;
90+
then {
91+
span_lint_and_sugg(
92+
cx,
93+
REF_IN_DEREF,
94+
object.span,
95+
"Creating a reference that is immediately dereferenced.",
96+
"try this",
97+
format!(
98+
"{}.{}",
99+
snippet(cx, inner.span, "_"),
100+
snippet(cx, field_name.span, "_")
101+
)
102+
);
103+
}
104+
}
105+
}
106+
}

tests/ui/unnecessary_ref.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#![feature(tool_attributes)]
2+
#![feature(stmt_expr_attributes)]
3+
4+
struct Outer {
5+
inner: u32,
6+
}
7+
8+
#[deny(ref_in_deref)]
9+
fn main() {
10+
let outer = Outer { inner: 0 };
11+
let inner = (&outer).inner;
12+
}

tests/ui/unnecessary_ref.stderr

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: Creating a reference that is immediately dereferenced.
2+
--> $DIR/unnecessary_ref.rs:11:17
3+
|
4+
11 | let inner = (&outer).inner;
5+
| ^^^^^^^^ help: try this: `outer.inner`
6+
|
7+
note: lint level defined here
8+
--> $DIR/unnecessary_ref.rs:8:8
9+
|
10+
8 | #[deny(ref_in_deref)]
11+
| ^^^^^^^^^^^^
12+
13+
error: aborting due to previous error
14+

0 commit comments

Comments
 (0)