Skip to content

Commit

Permalink
Merge pull request #2808 from Aaronepower/master
Browse files Browse the repository at this point in the history
Added lint for unnecessary references.
  • Loading branch information
oli-obk authored May 28, 2018
2 parents b979f62 + 8b67917 commit 0d1e06d
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 0 deletions.
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
reg.register_late_lint_pass(box if_let_redundant_pattern_matching::Pass);
reg.register_late_lint_pass(box partialeq_ne_impl::Pass);
reg.register_early_lint_pass(box reference::Pass);
reg.register_early_lint_pass(box reference::DerefPass);
reg.register_early_lint_pass(box double_parens::DoubleParens);
reg.register_late_lint_pass(box unused_io_amount::UnusedIoAmount);
reg.register_late_lint_pass(box large_enum_variant::LargeEnumVariant::new(conf.enum_variant_size_threshold));
Expand Down Expand Up @@ -809,6 +810,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
precedence::PRECEDENCE,
ranges::RANGE_ZIP_WITH_LEN,
reference::DEREF_ADDROF,
reference::REF_IN_DEREF,
swap::MANUAL_SWAP,
temporary_assignment::TEMPORARY_ASSIGNMENT,
transmute::CROSSPOINTER_TRANSMUTE,
Expand Down
50 changes: 50 additions & 0 deletions clippy_lints/src/reference.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,53 @@ impl EarlyLintPass for Pass {
}
}
}

/// **What it does:** Checks for references in expressions that use
/// auto dereference.
///
/// **Why is this bad?** The reference is a no-op and is automatically
/// dereferenced by the compiler and makes the code less clear.
///
/// **Example:**
/// ```rust
/// struct Point(u32, u32);
/// let point = Foo(30, 20);
/// let x = (&point).x;
/// ```
declare_clippy_lint! {
pub REF_IN_DEREF,
complexity,
"Use of reference in auto dereference expression."
}

pub struct DerefPass;

impl LintPass for DerefPass {
fn get_lints(&self) -> LintArray {
lint_array!(REF_IN_DEREF)
}
}

impl EarlyLintPass for DerefPass {
fn check_expr(&mut self, cx: &EarlyContext, e: &Expr) {
if_chain! {
if let ExprKind::Field(ref object, ref field_name) = e.node;
if let ExprKind::Paren(ref parened) = object.node;
if let ExprKind::AddrOf(_, ref inner) = parened.node;
then {
span_lint_and_sugg(
cx,
REF_IN_DEREF,
object.span,
"Creating a reference that is immediately dereferenced.",
"try this",
format!(
"{}.{}",
snippet(cx, inner.span, "_"),
snippet(cx, field_name.span, "_")
)
);
}
}
}
}
12 changes: 12 additions & 0 deletions tests/ui/unnecessary_ref.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#![feature(tool_attributes)]
#![feature(stmt_expr_attributes)]

struct Outer {
inner: u32,
}

#[deny(ref_in_deref)]
fn main() {
let outer = Outer { inner: 0 };
let inner = (&outer).inner;
}
14 changes: 14 additions & 0 deletions tests/ui/unnecessary_ref.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: Creating a reference that is immediately dereferenced.
--> $DIR/unnecessary_ref.rs:11:17
|
11 | let inner = (&outer).inner;
| ^^^^^^^^ help: try this: `outer.inner`
|
note: lint level defined here
--> $DIR/unnecessary_ref.rs:8:8
|
8 | #[deny(ref_in_deref)]
| ^^^^^^^^^^^^

error: aborting due to previous error

0 comments on commit 0d1e06d

Please sign in to comment.