Factor out is_qpath_def_path
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
|
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_hir::{BorrowKind, Expr, ExprKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
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::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::Box(e) | ExprKind::AddrOf(BorrowKind::Ref, _, e) => is_infinite(cx, e),
|
||||||
ExprKind::Call(path, _) => {
|
ExprKind::Call(path, _) => path_def_id(cx, path)
|
||||||
if let ExprKind::Path(ref qpath) = path.kind {
|
.map_or(false, |id| match_def_path(cx, id, &paths::ITER_REPEAT))
|
||||||
is_qpath_def_path(cx, qpath, path.hir_id, &paths::ITER_REPEAT).into()
|
.into(),
|
||||||
} else {
|
|
||||||
Finite
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
|
ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
|
||||||
_ => Finite,
|
_ => Finite,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1765,22 +1765,22 @@ where
|
|||||||
mod redundant_pattern_match {
|
mod redundant_pattern_match {
|
||||||
use super::REDUNDANT_PATTERN_MATCHING;
|
use super::REDUNDANT_PATTERN_MATCHING;
|
||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::higher;
|
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item, is_type_lang_item, match_type};
|
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 if_chain::if_chain;
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_data_structures::fx::FxHashSet;
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
|
use rustc_hir::LangItem::{OptionNone, PollPending};
|
||||||
use rustc_hir::{
|
use rustc_hir::{
|
||||||
intravisit::{walk_expr, Visitor},
|
intravisit::{walk_expr, Visitor},
|
||||||
Arm, Block, Expr, ExprKind, LangItem, MatchSource, Node, Pat, PatKind, QPath, UnOp,
|
Arm, Block, Expr, ExprKind, LangItem, MatchSource, Node, Pat, PatKind, QPath, UnOp,
|
||||||
};
|
};
|
||||||
use rustc_lint::LateContext;
|
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;
|
use rustc_span::sym;
|
||||||
|
|
||||||
pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
pub fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
||||||
@@ -1956,28 +1956,31 @@ mod redundant_pattern_match {
|
|||||||
has_else: bool,
|
has_else: bool,
|
||||||
) {
|
) {
|
||||||
// also look inside refs
|
// 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 we have &None for example, peel it so we can detect "if let None = x"
|
||||||
if let PatKind::Ref(inner, _mutability) = kind {
|
let check_pat = match let_pat.kind {
|
||||||
kind = &inner.kind;
|
PatKind::Ref(inner, _mutability) => inner,
|
||||||
}
|
_ => let_pat,
|
||||||
|
};
|
||||||
let op_ty = cx.typeck_results().expr_ty(let_expr);
|
let op_ty = cx.typeck_results().expr_ty(let_expr);
|
||||||
// Determine which function should be used, and the type contained by the corresponding
|
// Determine which function should be used, and the type contained by the corresponding
|
||||||
// variant.
|
// variant.
|
||||||
let (good_method, inner_ty) = match kind {
|
let (good_method, inner_ty) = match check_pat.kind {
|
||||||
PatKind::TupleStruct(ref path, [sub_pat], _) => {
|
PatKind::TupleStruct(ref qpath, [sub_pat], _) => {
|
||||||
if let PatKind::Wild = sub_pat.kind {
|
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))
|
("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))
|
("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)
|
("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)
|
("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)
|
("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)
|
("is_ipv6()", op_ty)
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@@ -2177,17 +2180,22 @@ mod redundant_pattern_match {
|
|||||||
should_be_left: &'a str,
|
should_be_left: &'a str,
|
||||||
should_be_right: &'a str,
|
should_be_right: &'a str,
|
||||||
) -> Option<&'a str> {
|
) -> Option<&'a str> {
|
||||||
let body_node_pair = if is_qpath_def_path(cx, path_left, arms[0].pat.hir_id, expected_left)
|
let left_id = cx
|
||||||
&& is_qpath_def_path(cx, path_right, arms[1].pat.hir_id, expected_right)
|
.typeck_results()
|
||||||
{
|
.qpath_res(path_left, arms[0].pat.hir_id)
|
||||||
(&(*arms[0].body).kind, &(*arms[1].body).kind)
|
.opt_def_id()?;
|
||||||
} else if is_qpath_def_path(cx, path_right, arms[1].pat.hir_id, expected_left)
|
let right_id = cx
|
||||||
&& is_qpath_def_path(cx, path_left, arms[0].pat.hir_id, expected_right)
|
.typeck_results()
|
||||||
{
|
.qpath_res(path_right, arms[1].pat.hir_id)
|
||||||
(&(*arms[1].body).kind, &(*arms[0].body).kind)
|
.opt_def_id()?;
|
||||||
} else {
|
let body_node_pair =
|
||||||
return None;
|
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 {
|
match body_node_pair {
|
||||||
(ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) {
|
(ExprKind::Lit(ref lit_left), ExprKind::Lit(ref lit_right)) => match (&lit_left.node, &lit_right.node) {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
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::source::snippet_with_applicability;
|
||||||
|
use clippy_utils::{match_def_path, path_def_id};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast;
|
use rustc_ast::ast;
|
||||||
use rustc_errors::Applicability;
|
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();
|
let ty_str = ty.to_string();
|
||||||
|
|
||||||
// `std::T::MAX` `std::T::MIN` constants
|
// `std::T::MAX` `std::T::MIN` constants
|
||||||
if let hir::ExprKind::Path(path) = &expr.kind {
|
if let Some(id) = path_def_id(cx, expr) {
|
||||||
if is_qpath_def_path(cx, path, expr.hir_id, &["core", &ty_str, "MAX"][..]) {
|
if match_def_path(cx, id, &["core", &ty_str, "MAX"]) {
|
||||||
return Some(MinMax::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);
|
return Some(MinMax::Min);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
/// 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.
|
/// 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 {
|
match expr.kind {
|
||||||
ExprKind::Closure(_, _, body_id, _, _) => is_body_identity_function(cx, cx.tcx.hir().body(body_id)),
|
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),
|
_ => path_def_id(cx, expr).map_or(false, |id| match_def_path(cx, id, &paths::CONVERT_IDENTITY)),
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user