Better precedence case management + more tests

This commit is contained in:
ThibsG 2020-03-21 19:34:56 +01:00
parent 72b9ae2a10
commit 3c2bbcf00e
5 changed files with 47 additions and 15 deletions

View File

@ -1,6 +1,6 @@
use crate::utils::{get_parent_expr, implements_trait, snippet, span_lint_and_sugg}; use crate::utils::{get_parent_expr, implements_trait, snippet, span_lint_and_sugg};
use if_chain::if_chain; 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_errors::Applicability;
use rustc_hir::{Expr, ExprKind}; use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass}; 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 { if let ExprKind::MethodCall(..) = parent_expr.kind {
return; return;
} }
// Check for unary precedence // Check for Expr that we don't want to be linted
if let ExprPrecedence::Unary = parent_expr.precedence() { let precedence = parent_expr.precedence();
return; 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(); let name = method_name.ident.as_str();

View File

@ -191,6 +191,7 @@ macro_rules! declare_clippy_lint {
mod copy_iterator; mod copy_iterator;
mod dbg_macro; mod dbg_macro;
mod default_trait_access; mod default_trait_access;
mod dereference;
mod derive; mod derive;
mod doc; mod doc;
mod double_comparison; mod double_comparison;

View File

@ -13,6 +13,15 @@ fn just_return(deref_str: &str) -> &str {
deref_str deref_str
} }
struct CustomVec(Vec<u8>);
impl Deref for CustomVec {
type Target = Vec<u8>;
fn deref(&self) -> &Vec<u8> {
&self.0
}
}
fn main() { fn main() {
let a: &mut String = &mut String::from("foo"); let a: &mut String = &mut String::from("foo");
@ -45,6 +54,9 @@ fn main() {
// following should not require linting // following should not require linting
let cv = CustomVec(vec![0, 42]);
let c = cv.deref()[0];
let b: &str = &*a.deref(); let b: &str = &*a.deref();
let b: String = a.deref().clone(); let b: String = a.deref().clone();

View File

@ -13,6 +13,15 @@ fn just_return(deref_str: &str) -> &str {
deref_str deref_str
} }
struct CustomVec(Vec<u8>);
impl Deref for CustomVec {
type Target = Vec<u8>;
fn deref(&self) -> &Vec<u8> {
&self.0
}
}
fn main() { fn main() {
let a: &mut String = &mut String::from("foo"); let a: &mut String = &mut String::from("foo");
@ -45,6 +54,9 @@ fn main() {
// following should not require linting // following should not require linting
let cv = CustomVec(vec![0, 42]);
let c = cv.deref()[0];
let b: &str = &*a.deref(); let b: &str = &*a.deref();
let b: String = a.deref().clone(); let b: String = a.deref().clone();

View File

@ -1,5 +1,5 @@
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:21:19 --> $DIR/dereference.rs:30:19
| |
LL | let b: &str = a.deref(); LL | let b: &str = a.deref();
| ^^^^^^^^^ help: try this: `&*a` | ^^^^^^^^^ help: try this: `&*a`
@ -7,61 +7,61 @@ LL | let b: &str = a.deref();
= note: `-D clippy::explicit-deref-methods` implied by `-D warnings` = note: `-D clippy::explicit-deref-methods` implied by `-D warnings`
error: explicit deref_mut method call error: explicit deref_mut method call
--> $DIR/dereference.rs:23:23 --> $DIR/dereference.rs:32:23
| |
LL | let b: &mut str = a.deref_mut(); LL | let b: &mut str = a.deref_mut();
| ^^^^^^^^^^^^^ help: try this: `&mut *a` | ^^^^^^^^^^^^^ help: try this: `&mut *a`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:26:39 --> $DIR/dereference.rs:35:39
| |
LL | let b: String = format!("{}, {}", a.deref(), a.deref()); LL | let b: String = format!("{}, {}", a.deref(), a.deref());
| ^^^^^^^^^ help: try this: `&*a` | ^^^^^^^^^ help: try this: `&*a`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:26:50 --> $DIR/dereference.rs:35:50
| |
LL | let b: String = format!("{}, {}", a.deref(), a.deref()); LL | let b: String = format!("{}, {}", a.deref(), a.deref());
| ^^^^^^^^^ help: try this: `&*a` | ^^^^^^^^^ help: try this: `&*a`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:28:20 --> $DIR/dereference.rs:37:20
| |
LL | println!("{}", a.deref()); LL | println!("{}", a.deref());
| ^^^^^^^^^ help: try this: `&*a` | ^^^^^^^^^ help: try this: `&*a`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:31:11 --> $DIR/dereference.rs:40:11
| |
LL | match a.deref() { LL | match a.deref() {
| ^^^^^^^^^ help: try this: `&*a` | ^^^^^^^^^ help: try this: `&*a`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:35:28 --> $DIR/dereference.rs:44:28
| |
LL | let b: String = concat(a.deref()); LL | let b: String = concat(a.deref());
| ^^^^^^^^^ help: try this: `&*a` | ^^^^^^^^^ help: try this: `&*a`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:37:13 --> $DIR/dereference.rs:46:13
| |
LL | let b = just_return(a).deref(); LL | let b = just_return(a).deref();
| ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)` | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:39:28 --> $DIR/dereference.rs:48:28
| |
LL | let b: String = concat(just_return(a).deref()); LL | let b: String = concat(just_return(a).deref());
| ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)` | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*just_return(a)`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:41:19 --> $DIR/dereference.rs:50:19
| |
LL | let b: &str = a.deref().deref(); LL | let b: &str = a.deref().deref();
| ^^^^^^^^^^^^^^^^^ help: try this: `&*a.deref()` | ^^^^^^^^^^^^^^^^^ help: try this: `&*a.deref()`
error: explicit deref method call error: explicit deref method call
--> $DIR/dereference.rs:44:13 --> $DIR/dereference.rs:53:13
| |
LL | let b = opt_a.unwrap().deref(); LL | let b = opt_a.unwrap().deref();
| ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()` | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `&*opt_a.unwrap()`