From 3c2bbcf00e3b97ab1fb03665b4afc7b7df0cd25e Mon Sep 17 00:00:00 2001 From: ThibsG Date: Sat, 21 Mar 2020 19:34:56 +0100 Subject: [PATCH] Better precedence case management + more tests --- clippy_lints/src/dereference.rs | 15 +++++++++++---- clippy_lints/src/lib.rs | 1 + tests/ui/dereference.fixed | 12 ++++++++++++ tests/ui/dereference.rs | 12 ++++++++++++ tests/ui/dereference.stderr | 22 +++++++++++----------- 5 files changed, 47 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index f5d82c54916..68ec07e2bcb 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1,6 +1,6 @@ use crate::utils::{get_parent_expr, implements_trait, snippet, span_lint_and_sugg}; use if_chain::if_chain; -use rustc_ast::util::parser::ExprPrecedence; +use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX, PREC_PREFIX}; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -51,9 +51,16 @@ fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { if let ExprKind::MethodCall(..) = parent_expr.kind { return; } - // Check for unary precedence - if let ExprPrecedence::Unary = parent_expr.precedence() { - return; + // Check for Expr that we don't want to be linted + let precedence = parent_expr.precedence(); + match precedence { + // Lint a Call is ok though + ExprPrecedence::Call | ExprPrecedence::AddrOf => (), + _ => { + if precedence.order() >= PREC_PREFIX && precedence.order() <= PREC_POSTFIX { + return; + } + } } } let name = method_name.ident.as_str(); diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b6b6a0e7d21..de1bab3a0b9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -191,6 +191,7 @@ macro_rules! declare_clippy_lint { mod copy_iterator; mod dbg_macro; mod default_trait_access; +mod dereference; mod derive; mod doc; mod double_comparison; diff --git a/tests/ui/dereference.fixed b/tests/ui/dereference.fixed index 51e3d512cdb..459ca91b93b 100644 --- a/tests/ui/dereference.fixed +++ b/tests/ui/dereference.fixed @@ -13,6 +13,15 @@ fn just_return(deref_str: &str) -> &str { deref_str } +struct CustomVec(Vec); +impl Deref for CustomVec { + type Target = Vec; + + fn deref(&self) -> &Vec { + &self.0 + } +} + fn main() { let a: &mut String = &mut String::from("foo"); @@ -45,6 +54,9 @@ fn main() { // following should not require linting + let cv = CustomVec(vec![0, 42]); + let c = cv.deref()[0]; + let b: &str = &*a.deref(); let b: String = a.deref().clone(); diff --git a/tests/ui/dereference.rs b/tests/ui/dereference.rs index 3a595337411..8dc5272e67f 100644 --- a/tests/ui/dereference.rs +++ b/tests/ui/dereference.rs @@ -13,6 +13,15 @@ fn just_return(deref_str: &str) -> &str { deref_str } +struct CustomVec(Vec); +impl Deref for CustomVec { + type Target = Vec; + + fn deref(&self) -> &Vec { + &self.0 + } +} + fn main() { let a: &mut String = &mut String::from("foo"); @@ -45,6 +54,9 @@ fn main() { // following should not require linting + let cv = CustomVec(vec![0, 42]); + let c = cv.deref()[0]; + let b: &str = &*a.deref(); let b: String = a.deref().clone(); diff --git a/tests/ui/dereference.stderr b/tests/ui/dereference.stderr index d159214db2f..d26b462a433 100644 --- a/tests/ui/dereference.stderr +++ b/tests/ui/dereference.stderr @@ -1,5 +1,5 @@ error: explicit deref method call - --> $DIR/dereference.rs:21:19 + --> $DIR/dereference.rs:30:19 | LL | let b: &str = a.deref(); | ^^^^^^^^^ help: try this: `&*a` @@ -7,61 +7,61 @@ LL | let b: &str = a.deref(); = note: `-D clippy::explicit-deref-methods` implied by `-D warnings` error: explicit deref_mut method call - --> $DIR/dereference.rs:23:23 + --> $DIR/dereference.rs:32:23 | LL | let b: &mut str = a.deref_mut(); | ^^^^^^^^^^^^^ help: try this: `&mut *a` error: explicit deref method call - --> $DIR/dereference.rs:26:39 + --> $DIR/dereference.rs:35:39 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit deref method call - --> $DIR/dereference.rs:26:50 + --> $DIR/dereference.rs:35:50 | LL | let b: String = format!("{}, {}", a.deref(), a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit deref method call - --> $DIR/dereference.rs:28:20 + --> $DIR/dereference.rs:37:20 | LL | println!("{}", a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit deref method call - --> $DIR/dereference.rs:31:11 + --> $DIR/dereference.rs:40:11 | LL | match a.deref() { | ^^^^^^^^^ help: try this: `&*a` error: explicit deref method call - --> $DIR/dereference.rs:35:28 + --> $DIR/dereference.rs:44:28 | LL | let b: String = concat(a.deref()); | ^^^^^^^^^ help: try this: `&*a` error: explicit deref method call - --> $DIR/dereference.rs:37:13 + --> $DIR/dereference.rs:46:13 | LL | let b = just_return(a).deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)` error: explicit deref method call - --> $DIR/dereference.rs:39:28 + --> $DIR/dereference.rs:48:28 | LL | let b: String = concat(just_return(a).deref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)` error: explicit deref method call - --> $DIR/dereference.rs:41:19 + --> $DIR/dereference.rs:50:19 | LL | let b: &str = a.deref().deref(); | ^^^^^^^^^^^^^^^^^ help: try this: `&*a.deref()` error: explicit deref method call - --> $DIR/dereference.rs:44:13 + --> $DIR/dereference.rs:53:13 | LL | let b = opt_a.unwrap().deref(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()`