]> git.lizzy.rs Git - rust.git/blobdiff - clippy_lints/src/methods/or_fun_call.rs
Merge remote-tracking branch 'upstream/beta' into backport_remerge
[rust.git] / clippy_lints / src / methods / or_fun_call.rs
index ef615b0aa40a8e61995b4e63692ab9fe86d4cc3e..30ed1d665a907d1cf1bb8d4ea3208a0a48023e5b 100644 (file)
@@ -1,7 +1,9 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
 use clippy_utils::eager_or_lazy::is_lazyness_candidate;
+use clippy_utils::is_trait_item;
 use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_macro_callsite};
-use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, match_type};
+use clippy_utils::ty::implements_trait;
+use clippy_utils::ty::{is_type_diagnostic_item, match_type};
 use clippy_utils::{contains_return, last_path_segment, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
@@ -34,15 +36,23 @@ fn check_unwrap_or_default(
         or_has_args: bool,
         span: Span,
     ) -> bool {
+        let is_default_default = || is_trait_item(cx, fun, sym::Default);
+
+        let implements_default = |arg, default_trait_id| {
+            let arg_ty = cx.typeck_results().expr_ty(arg);
+            implements_trait(cx, arg_ty, default_trait_id, &[])
+        };
+
         if_chain! {
             if !or_has_args;
             if name == "unwrap_or";
             if let hir::ExprKind::Path(ref qpath) = fun.kind;
-            let path = last_path_segment(qpath).ident.name;
-            if matches!(path, kw::Default | sym::new);
-            let arg_ty = cx.typeck_results().expr_ty(arg);
             if let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default);
-            if implements_trait(cx, arg_ty, default_trait_id, &[]);
+            let path = last_path_segment(qpath).ident.name;
+            // needs to target Default::default in particular or be *::new and have a Default impl
+            // available
+            if (matches!(path, kw::Default) && is_default_default())
+                || (matches!(path, sym::new) && implements_default(arg, default_trait_id));
 
             then {
                 let mut applicability = Applicability::MachineApplicable;
@@ -86,9 +96,9 @@ fn check_general_case<'tcx>(
             (&paths::RESULT, true, &["or", "unwrap_or"], "else"),
         ];
 
-        if let hir::ExprKind::MethodCall(path, _, args, _) = &arg.kind {
+        if let hir::ExprKind::MethodCall(path, _, [self_arg, ..], _) = &arg.kind {
             if path.ident.name == sym::len {
-                let ty = cx.typeck_results().expr_ty(&args[0]).peel_refs();
+                let ty = cx.typeck_results().expr_ty(self_arg).peel_refs();
 
                 match ty.kind() {
                     ty::Slice(_) | ty::Array(_, _) | ty::Str => return,