diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index f5d82c549163..51dea66c74de 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,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Dereferencing { 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 => (), // | ExprPrecedence::MethodCall + _ => { + if precedence.order() >= PREC_PREFIX && precedence.order() <= PREC_POSTFIX { + // println!("Sup:\nexpr: {:#?}\nparent_expr: {:#?}\nprec: {:#?}", expr.span, parent_expr, precedence); + return; + } + } } } let name = method_name.ident.as_str(); diff --git a/tests/ui/dereference.fixed b/tests/ui/dereference.fixed index 51e3d512cdba..459ca91b93b9 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 3a5953374112..8dc5272e67fa 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 d159214db2ff..d26b462a4336 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()`