]> git.lizzy.rs Git - rust.git/commitdiff
check for Deref conversions
authorwartman4404 <wartman4404@my.mstc.edu>
Wed, 4 Nov 2015 03:11:40 +0000 (21:11 -0600)
committerwartman4404 <wartman4404@my.mstc.edu>
Wed, 4 Nov 2015 03:11:40 +0000 (21:11 -0600)
README.md
src/eta_reduction.rs
src/map_clone.rs
src/utils.rs
tests/compile-fail/map_clone.rs

index fcfeca1509eb3adefa4f5a392fbb54212a721665..4c23d6994d298fc9ed2cc7829f2e41b20b027422 100644 (file)
--- a/README.md
+++ b/README.md
@@ -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
 -------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
index 7226a4bad05a696d60c9dffedd4a8e1b12ec5af7..855ea51ee8eacc395a48caf87025302fa5db16b1 100644 (file)
@@ -2,7 +2,7 @@
 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 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
     }
 }
 
-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() {
index 570ee91dd7bd133e78cc9fc2ab20ef2b0d950c61..e93a8221145847a5f3957cd0e41e478101d9a573 100644 (file)
@@ -2,7 +2,7 @@
 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 @@ fn check_expr(&mut self, cx: &LateContext, expr: &Expr) {
                 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),
     }
 }
 
index 7cbb532cf22edea666d22cb64cabe6a0eab36256..757d7bc379d76eb988bfccf764e0e3f6252d253d 100644 (file)
@@ -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! {
index 9d9f253defe89b49369d6e9e812b36257ba0fd2f..f6241114a83c545356e04adf8bb5b065e39fffa9 100644 (file)
@@ -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() { }