From bd583d91a1bf3717f724a38531e142aa4a9ee6cc Mon Sep 17 00:00:00 2001
From: Cameron Steffen <cam.steffen94@gmail.com>
Date: Thu, 6 Jan 2022 12:41:17 -0600
Subject: [PATCH] Factor out is_qpath_def_path

---
 clippy_lints/src/infinite_iter.rs             | 12 ++--
 clippy_lints/src/matches.rs                   | 62 +++++++++++--------
 .../methods/manual_saturating_arithmetic.rs   |  8 +--
 clippy_utils/src/lib.rs                       | 10 +--
 4 files changed, 44 insertions(+), 48 deletions(-)

diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs
index 3008e86ef8b..b6badef02f5 100644
--- a/clippy_lints/src/infinite_iter.rs
+++ b/clippy_lints/src/infinite_iter.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint;
 use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
-use clippy_utils::{get_trait_def_id, higher, is_qpath_def_path, paths};
+use clippy_utils::{get_trait_def_id, higher, match_def_path, path_def_id, paths};
 use rustc_hir::{BorrowKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -167,13 +167,9 @@ fn is_infinite(cx: &LateContext<'_>, expr: &Expr<'_>) -> Finiteness {
         },
         ExprKind::Block(block, _) => block.expr.as_ref().map_or(Finite, |e| is_infinite(cx, e)),
         ExprKind::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
-        ExprKind::Call(path, _) => {
-            if let ExprKind::Path(ref qpath) = path.kind {
-                is_qpath_def_path(cx, qpath, path.hir_id, &paths::ITER_REPEAT).into()
-            } else {
-                Finite
-            }
-        },
+        ExprKind::Call(path, _) => path_def_id(cx, path)
+            .map_or(false, |id| match_def_path(cx, id, &paths::ITER_REPEAT))
+            .into(),
         ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
         _ => Finite,
     }
diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs
index 2579404fb18..81ae4dacdf6 100644
--- a/clippy_lints/src/matches.rs
+++ b/clippy_lints/src/matches.rs
@@ -1765,22 +1765,22 @@ where
 mod redundant_pattern_match {
     use super::REDUNDANT_PATTERN_MATCHING;
     use clippy_utils::diagnostics::span_lint_and_then;
-    use clippy_utils::higher;
     use clippy_utils::source::snippet;
     use clippy_utils::sugg::Sugg;
     use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, is_type_lang_item, match_type};
-    use clippy_utils::{is_lang_ctor, is_qpath_def_path, is_trait_method, paths};
+    use clippy_utils::{higher, match_def_path};
+    use clippy_utils::{is_lang_ctor, is_trait_method, paths};
     use if_chain::if_chain;
     use rustc_ast::ast::LitKind;
     use rustc_data_structures::fx::FxHashSet;
     use rustc_errors::Applicability;
-    use rustc_hir::LangItem::{OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
+    use rustc_hir::LangItem::{OptionNone, PollPending};
     use rustc_hir::{
         intravisit::{walk_expr, Visitor},
         Arm, Block, Expr, ExprKind, LangItem, MatchSource, Node, Pat, PatKind, QPath, UnOp,
     };
     use rustc_lint::LateContext;
-    use rustc_middle::ty::{self, subst::GenericArgKind, Ty};
+    use rustc_middle::ty::{self, subst::GenericArgKind, DefIdTree, Ty};
     use rustc_span::sym;
 
     pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
@@ -1956,28 +1956,31 @@ mod redundant_pattern_match {
         has_else: bool,
     ) {
         // also look inside refs
-        let mut kind = &let_pat.kind;
         // if we have &None for example, peel it so we can detect "if let None = x"
-        if let PatKind::Ref(inner, _mutability) = kind {
-            kind = &inner.kind;
-        }
+        let check_pat = match let_pat.kind {
+            PatKind::Ref(inner, _mutability) => inner,
+            _ => let_pat,
+        };
         let op_ty = cx.typeck_results().expr_ty(let_expr);
         // Determine which function should be used, and the type contained by the corresponding
         // variant.
-        let (good_method, inner_ty) = match kind {
-            PatKind::TupleStruct(ref path, [sub_pat], _) => {
+        let (good_method, inner_ty) = match check_pat.kind {
+            PatKind::TupleStruct(ref qpath, [sub_pat], _) => {
                 if let PatKind::Wild = sub_pat.kind {
-                    if is_lang_ctor(cx, path, ResultOk) {
+                    let res = cx.typeck_results().qpath_res(qpath, check_pat.hir_id);
+                    let Some(id) = res.opt_def_id().and_then(|ctor_id| cx.tcx.parent(ctor_id)) else { return };
+                    let lang_items = cx.tcx.lang_items();
+                    if Some(id) == lang_items.result_ok_variant() {
                         ("is_ok()", try_get_generic_ty(op_ty, 0).unwrap_or(op_ty))
-                    } else if is_lang_ctor(cx, path, ResultErr) {
+                    } else if Some(id) == lang_items.result_err_variant() {
                         ("is_err()", try_get_generic_ty(op_ty, 1).unwrap_or(op_ty))
-                    } else if is_lang_ctor(cx, path, OptionSome) {
+                    } else if Some(id) == lang_items.option_some_variant() {
                         ("is_some()", op_ty)
-                    } else if is_lang_ctor(cx, path, PollReady) {
+                    } else if Some(id) == lang_items.poll_ready_variant() {
                         ("is_ready()", op_ty)
-                    } else if is_qpath_def_path(cx, path, sub_pat.hir_id, &paths::IPADDR_V4) {
+                    } else if match_def_path(cx, id, &paths::IPADDR_V4) {
                         ("is_ipv4()", op_ty)
-                    } else if is_qpath_def_path(cx, path, sub_pat.hir_id, &paths::IPADDR_V6) {
+                    } else if match_def_path(cx, id, &paths::IPADDR_V6) {
                         ("is_ipv6()", op_ty)
                     } else {
                         return;
@@ -2177,17 +2180,22 @@ mod redundant_pattern_match {
         should_be_left: &'a str,
         should_be_right: &'a str,
     ) -> Option<&'a str> {
-        let body_node_pair = if is_qpath_def_path(cx, path_left, arms[0].pat.hir_id, expected_left)
-            && is_qpath_def_path(cx, path_right, arms[1].pat.hir_id, expected_right)
-        {
-            (&(*arms[0].body).kind, &(*arms[1].body).kind)
-        } else if is_qpath_def_path(cx, path_right, arms[1].pat.hir_id, expected_left)
-            && is_qpath_def_path(cx, path_left, arms[0].pat.hir_id, expected_right)
-        {
-            (&(*arms[1].body).kind, &(*arms[0].body).kind)
-        } else {
-            return None;
-        };
+        let left_id = cx
+            .typeck_results()
+            .qpath_res(path_left, arms[0].pat.hir_id)
+            .opt_def_id()?;
+        let right_id = cx
+            .typeck_results()
+            .qpath_res(path_right, arms[1].pat.hir_id)
+            .opt_def_id()?;
+        let body_node_pair =
+            if match_def_path(cx, left_id, expected_left) && match_def_path(cx, right_id, expected_right) {
+                (&(*arms[0].body).kind, &(*arms[1].body).kind)
+            } else if match_def_path(cx, right_id, expected_left) && match_def_path(cx, right_id, expected_right) {
+                (&(*arms[1].body).kind, &(*arms[0].body).kind)
+            } else {
+                return None;
+            };
 
         match body_node_pair {
             (ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) {
diff --git a/clippy_lints/src/methods/manual_saturating_arithmetic.rs b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
index 4307cbf0050..0fe510beaa0 100644
--- a/clippy_lints/src/methods/manual_saturating_arithmetic.rs
+++ b/clippy_lints/src/methods/manual_saturating_arithmetic.rs
@@ -1,6 +1,6 @@
 use clippy_utils::diagnostics::span_lint_and_sugg;
-use clippy_utils::is_qpath_def_path;
 use clippy_utils::source::snippet_with_applicability;
+use clippy_utils::{match_def_path, path_def_id};
 use if_chain::if_chain;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
@@ -93,12 +93,12 @@ fn is_min_or_max<'tcx>(cx: &LateContext<'tcx>, expr: &hir::Expr<'_>) -> Option<M
     let ty_str = ty.to_string();
 
     // `std::T::MAX` `std::T::MIN` constants
-    if let hir::ExprKind::Path(path) = &expr.kind {
-        if is_qpath_def_path(cx, path, expr.hir_id, &["core", &ty_str, "MAX"][..]) {
+    if let Some(id) = path_def_id(cx, expr) {
+        if match_def_path(cx, id, &["core", &ty_str, "MAX"]) {
             return Some(MinMax::Max);
         }
 
-        if is_qpath_def_path(cx, path, expr.hir_id, &["core", &ty_str, "MIN"][..]) {
+        if match_def_path(cx, id, &["core", &ty_str, "MIN"]) {
             return Some(MinMax::Min);
         }
     }
diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs
index 62066987232..f4fdb7c13d3 100644
--- a/clippy_utils/src/lib.rs
+++ b/clippy_utils/src/lib.rs
@@ -357,13 +357,6 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool {
     }
 }
 
-/// Resolves the path to a `DefId` and checks if it matches the given path.
-pub fn is_qpath_def_path(cx: &LateContext<'_>, path: &QPath<'_>, hir_id: HirId, segments: &[&str]) -> bool {
-    cx.qpath_res(path, hir_id)
-        .opt_def_id()
-        .map_or(false, |id| match_def_path(cx, id, segments))
-}
-
 /// If the expression is a path, resolves it to a `DefId` and checks if it matches the given path.
 ///
 /// Please use `is_expr_diagnostic_item` if the target is a diagnostic item.
@@ -1775,8 +1768,7 @@ pub fn is_expr_identity_function(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool
 
     match expr.kind {
         ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
-        ExprKind::Path(ref path) => is_qpath_def_path(cx, path, expr.hir_id, &paths::CONVERT_IDENTITY),
-        _ => false,
+        _ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)),
     }
 }