about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-08-30 06:07:41 +0000
committerbors <bors@rust-lang.org>2019-08-30 06:07:41 +0000
commit2bff3d87d597b7756e7126d0dc6345c2b822ecb7 (patch)
tree3942487d18ff9d93dc4286de534a272b0dfb9d8a
parent28a8a6a4834db7b6869d3b645528b31002deba57 (diff)
parent0c8332558b25273ecc3df483044fa3bb8f31eeeb (diff)
downloadrust-2bff3d87d597b7756e7126d0dc6345c2b822ecb7.tar.gz
rust-2bff3d87d597b7756e7126d0dc6345c2b822ecb7.zip
Auto merge of #4446 - mikerite:fix-4437, r=phansch
Fix `match_as_ref` bad suggestion

Fixes #4437

changelog: Fix `match_as_ref` bad suggestion
-rw-r--r--clippy_lints/src/matches.rs23
-rw-r--r--tests/ui/match_as_ref.fixed21
-rw-r--r--tests/ui/match_as_ref.rs24
-rw-r--r--tests/ui/match_as_ref.stderr11
4 files changed, 76 insertions, 3 deletions
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index 6b6fd2bb208..2a65ea000db 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -624,6 +624,24 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &
             } else {
                 "as_mut"
             };
+
+            let output_ty = cx.tables.expr_ty(expr);
+            let input_ty = cx.tables.expr_ty(ex);
+
+            let cast = if_chain! {
+                if let ty::Adt(_, substs) = input_ty.sty;
+                let input_ty = substs.type_at(0);
+                if let ty::Adt(_, substs) = output_ty.sty;
+                let output_ty = substs.type_at(0);
+                if let ty::Ref(_, output_ty, _) = output_ty.sty;
+                if input_ty != output_ty;
+                then {
+                    ".map(|x| x as _)"
+                } else {
+                    ""
+                }
+            };
+
             let mut applicability = Applicability::MachineApplicable;
             span_lint_and_sugg(
                 cx,
@@ -632,9 +650,10 @@ fn check_match_as_ref(cx: &LateContext<'_, '_>, ex: &Expr, arms: &[Arm], expr: &
                 &format!("use {}() instead", suggestion),
                 "try this",
                 format!(
-                    "{}.{}()",
+                    "{}.{}(){}",
                     snippet_with_applicability(cx, ex.span, "_", &mut applicability),
-                    suggestion
+                    suggestion,
+                    cast,
                 ),
                 applicability,
             )
diff --git a/tests/ui/match_as_ref.fixed b/tests/ui/match_as_ref.fixed
index 75085367f96..c61eb921664 100644
--- a/tests/ui/match_as_ref.fixed
+++ b/tests/ui/match_as_ref.fixed
@@ -11,4 +11,25 @@ fn match_as_ref() {
     let borrow_mut: Option<&mut ()> = mut_owned.as_mut();
 }
 
+mod issue4437 {
+    use std::{error::Error, fmt, num::ParseIntError};
+
+    #[derive(Debug)]
+    struct E {
+        source: Option<ParseIntError>,
+    }
+
+    impl Error for E {
+        fn source(&self) -> Option<&(dyn Error + 'static)> {
+            self.source.as_ref().map(|x| x as _)
+        }
+    }
+
+    impl fmt::Display for E {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            unimplemented!()
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/match_as_ref.rs b/tests/ui/match_as_ref.rs
index 62c06f35251..2fbd0b255fa 100644
--- a/tests/ui/match_as_ref.rs
+++ b/tests/ui/match_as_ref.rs
@@ -17,4 +17,28 @@ fn match_as_ref() {
     };
 }
 
+mod issue4437 {
+    use std::{error::Error, fmt, num::ParseIntError};
+
+    #[derive(Debug)]
+    struct E {
+        source: Option<ParseIntError>,
+    }
+
+    impl Error for E {
+        fn source(&self) -> Option<&(dyn Error + 'static)> {
+            match self.source {
+                Some(ref s) => Some(s),
+                None => None,
+            }
+        }
+    }
+
+    impl fmt::Display for E {
+        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+            unimplemented!()
+        }
+    }
+}
+
 fn main() {}
diff --git a/tests/ui/match_as_ref.stderr b/tests/ui/match_as_ref.stderr
index 09115b85d35..dd4739d1ff2 100644
--- a/tests/ui/match_as_ref.stderr
+++ b/tests/ui/match_as_ref.stderr
@@ -20,5 +20,14 @@ LL | |         Some(ref mut v) => Some(v),
 LL | |     };
    | |_____^ help: try this: `mut_owned.as_mut()`
 
-error: aborting due to 2 previous errors
+error: use as_ref() instead
+  --> $DIR/match_as_ref.rs:30:13
+   |
+LL | /             match self.source {
+LL | |                 Some(ref s) => Some(s),
+LL | |                 None => None,
+LL | |             }
+   | |_____________^ help: try this: `self.source.as_ref().map(|x| x as _)`
+
+error: aborting due to 3 previous errors