check for Deref conversions
This commit is contained in:
parent
414c0d20f7
commit
764eedd050
5 changed files with 37 additions and 15 deletions
|
@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your Rust code.
|
|||
[Jump to usage instructions](#usage)
|
||||
|
||||
##Lints
|
||||
There are 71 lints included in this crate:
|
||||
There are 72 lints included in this crate:
|
||||
|
||||
name | default | meaning
|
||||
-------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -2,7 +2,7 @@ use rustc::lint::*;
|
|||
use rustc_front::hir::*;
|
||||
use rustc::middle::ty;
|
||||
|
||||
use utils::{snippet, span_lint};
|
||||
use utils::{snippet, span_lint, is_adjusted};
|
||||
|
||||
|
||||
#[allow(missing_copy_implementations)]
|
||||
|
@ -32,10 +32,6 @@ impl LateLintPass for EtaPass {
|
|||
}
|
||||
}
|
||||
|
||||
fn is_adjusted(cx: &LateContext, e: &Expr) -> bool {
|
||||
cx.tcx.tables.borrow().adjustments.get(&e.id).is_some()
|
||||
}
|
||||
|
||||
fn check_closure(cx: &LateContext, expr: &Expr) {
|
||||
if let ExprClosure(_, ref decl, ref blk) = expr.node {
|
||||
if !blk.stmts.is_empty() {
|
||||
|
|
|
@ -2,7 +2,7 @@ use rustc::lint::*;
|
|||
use rustc_front::hir::*;
|
||||
use syntax::ast::Ident;
|
||||
use utils::OPTION_PATH;
|
||||
use utils::{match_trait_method, match_type, snippet, span_help_and_lint};
|
||||
use utils::{is_adjusted, match_trait_method, match_type, snippet, span_help_and_lint};
|
||||
use utils::{walk_ptrs_ty, walk_ptrs_ty_depth};
|
||||
|
||||
declare_lint!(pub MAP_CLONE, Warn,
|
||||
|
@ -30,7 +30,7 @@ impl LateLintPass for MapClonePass {
|
|||
let Some(type_name) = get_type_name(cx, expr, &args[0])
|
||||
], {
|
||||
// look for derefs, for .map(|x| *x)
|
||||
if only_derefs(&*closure_expr, arg_ident) &&
|
||||
if only_derefs(cx, &*closure_expr, arg_ident) &&
|
||||
// .cloned() only removes one level of indirection, don't lint on more
|
||||
walk_ptrs_ty_depth(cx.tcx.pat_ty(&*decl.inputs[0].pat)).1 == 1
|
||||
{
|
||||
|
@ -85,13 +85,12 @@ fn get_arg_name(pat: &Pat) -> Option<Ident> {
|
|||
}
|
||||
}
|
||||
|
||||
fn only_derefs(expr: &Expr, id: Ident) -> bool {
|
||||
if expr_eq_ident(expr, id) {
|
||||
true
|
||||
} else if let ExprUnary(UnDeref, ref subexpr) = expr.node {
|
||||
only_derefs(subexpr, id)
|
||||
} else {
|
||||
false
|
||||
fn only_derefs(cx: &LateContext, expr: &Expr, id: Ident) -> bool {
|
||||
match expr.node {
|
||||
ExprUnary(UnDeref, ref subexpr) if !is_adjusted(cx, subexpr) => {
|
||||
only_derefs(cx, subexpr, id)
|
||||
},
|
||||
_ => expr_eq_ident(expr, id),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -347,6 +347,10 @@ pub fn is_integer_literal(expr: &Expr, value: u64) -> bool
|
|||
false
|
||||
}
|
||||
|
||||
pub fn is_adjusted(cx: &LateContext, e: &Expr) -> bool {
|
||||
cx.tcx.tables.borrow().adjustments.get(&e.id).is_some()
|
||||
}
|
||||
|
||||
/// Produce a nested chain of if-lets and ifs from the patterns:
|
||||
///
|
||||
/// if_let_chain! {
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
|
||||
#![allow(unused)]
|
||||
|
||||
use std::ops::Deref;
|
||||
|
||||
fn map_clone_iter() {
|
||||
let x = [1,2,3];
|
||||
x.iter().map(|y| y.clone()); //~ ERROR you seem to be using .map()
|
||||
|
@ -66,4 +68,25 @@ fn map_clone_other() {
|
|||
x.map(|y| *y);
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
struct UnusualDeref;
|
||||
static NINE: i32 = 9;
|
||||
|
||||
impl Deref for UnusualDeref {
|
||||
type Target = i32;
|
||||
fn deref(&self) -> &i32 { &NINE }
|
||||
}
|
||||
|
||||
fn map_clone_deref() {
|
||||
let x = Some(UnusualDeref);
|
||||
let _: Option<UnusualDeref> = x.as_ref().map(|y| *y); //~ ERROR you seem to be using .map()
|
||||
//~^ HELP try
|
||||
|
||||
// Not linted: using deref conversion
|
||||
let _: Option<i32> = x.map(|y| *y);
|
||||
|
||||
// Not linted: using regular deref but also deref conversion
|
||||
let _: Option<i32> = x.as_ref().map(|y| **y);
|
||||
}
|
||||
|
||||
fn main() { }
|
||||
|
|
Loading…
Add table
Reference in a new issue