mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
Replace is_lang_ctor
with is_res_lang_ctor
This commit is contained in:
parent
f8ba19287d
commit
8e7af6b429
@ -1,7 +1,9 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_help;
|
use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
|
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
|
||||||
use clippy_utils::source::snippet_with_macro_callsite;
|
use clippy_utils::source::snippet_with_macro_callsite;
|
||||||
use clippy_utils::{contains_return, higher, is_else_clause, is_lang_ctor, meets_msrv, msrvs, peel_blocks};
|
use clippy_utils::{
|
||||||
|
contains_return, higher, is_else_clause, is_res_lang_ctor, meets_msrv, msrvs, path_res, peel_blocks,
|
||||||
|
};
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||||
use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
|
use rustc_hir::{Expr, ExprKind, Stmt, StmtKind};
|
||||||
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
use rustc_lint::{LateContext, LateLintPass, LintContext};
|
||||||
@ -76,10 +78,8 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
|
|||||||
&& let ExprKind::Block(then_block, _) = then.kind
|
&& let ExprKind::Block(then_block, _) = then.kind
|
||||||
&& let Some(then_expr) = then_block.expr
|
&& let Some(then_expr) = then_block.expr
|
||||||
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
|
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
|
||||||
&& let ExprKind::Path(ref then_call_qpath) = then_call.kind
|
&& is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
|
||||||
&& is_lang_ctor(cx, then_call_qpath, OptionSome)
|
&& is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
|
||||||
&& let ExprKind::Path(ref qpath) = peel_blocks(els).kind
|
|
||||||
&& is_lang_ctor(cx, qpath, OptionNone)
|
|
||||||
&& !stmts_contains_early_return(then_block.stmts)
|
&& !stmts_contains_early_return(then_block.stmts)
|
||||||
{
|
{
|
||||||
let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
|
let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use super::utils::make_iterator_snippet;
|
use super::utils::make_iterator_snippet;
|
||||||
use super::MANUAL_FIND;
|
use super::MANUAL_FIND;
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
diagnostics::span_lint_and_then, higher, is_lang_ctor, path_res, peel_blocks_with_stmt,
|
diagnostics::span_lint_and_then, higher, is_res_lang_ctor, path_res, peel_blocks_with_stmt,
|
||||||
source::snippet_with_applicability, ty::implements_trait,
|
source::snippet_with_applicability, ty::implements_trait,
|
||||||
};
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
@ -30,8 +30,8 @@ pub(super) fn check<'tcx>(
|
|||||||
if let [stmt] = block.stmts;
|
if let [stmt] = block.stmts;
|
||||||
if let StmtKind::Semi(semi) = stmt.kind;
|
if let StmtKind::Semi(semi) = stmt.kind;
|
||||||
if let ExprKind::Ret(Some(ret_value)) = semi.kind;
|
if let ExprKind::Ret(Some(ret_value)) = semi.kind;
|
||||||
if let ExprKind::Call(Expr { kind: ExprKind::Path(ctor), .. }, [inner_ret]) = ret_value.kind;
|
if let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind;
|
||||||
if is_lang_ctor(cx, ctor, LangItem::OptionSome);
|
if is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome);
|
||||||
if path_res(cx, inner_ret) == Res::Local(binding_id);
|
if path_res(cx, inner_ret) == Res::Local(binding_id);
|
||||||
if let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr);
|
if let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr);
|
||||||
then {
|
then {
|
||||||
@ -143,8 +143,7 @@ fn last_stmt_and_ret<'tcx>(
|
|||||||
if let Some((_, Node::Block(block))) = parent_iter.next();
|
if let Some((_, Node::Block(block))) = parent_iter.next();
|
||||||
if let Some((last_stmt, last_ret)) = extract(block);
|
if let Some((last_stmt, last_ret)) = extract(block);
|
||||||
if last_stmt.hir_id == node_hir;
|
if last_stmt.hir_id == node_hir;
|
||||||
if let ExprKind::Path(path) = &last_ret.kind;
|
if is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone);
|
||||||
if is_lang_ctor(cx, path, LangItem::OptionNone);
|
|
||||||
if let Some((_, Node::Expr(_block))) = parent_iter.next();
|
if let Some((_, Node::Expr(_block))) = parent_iter.next();
|
||||||
// This includes the function header
|
// This includes the function header
|
||||||
if let Some((_, func)) = parent_iter.next();
|
if let Some((_, func)) = parent_iter.next();
|
||||||
|
@ -3,13 +3,13 @@ use super::MANUAL_FLATTEN;
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::higher;
|
use clippy_utils::higher;
|
||||||
use clippy_utils::visitors::is_local_used;
|
use clippy_utils::visitors::is_local_used;
|
||||||
use clippy_utils::{is_lang_ctor, path_to_local_id, peel_blocks_with_stmt};
|
use clippy_utils::{path_to_local_id, peel_blocks_with_stmt};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{OptionSome, ResultOk};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::{Expr, Pat, PatKind};
|
use rustc_hir::{Expr, Pat, PatKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::ty;
|
use rustc_middle::ty::{self, DefIdTree};
|
||||||
use rustc_span::source_map::Span;
|
use rustc_span::source_map::Span;
|
||||||
|
|
||||||
/// Check for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the
|
/// Check for unnecessary `if let` usage in a for loop where only the `Some` or `Ok` variant of the
|
||||||
@ -30,8 +30,10 @@ pub(super) fn check<'tcx>(
|
|||||||
if path_to_local_id(let_expr, pat_hir_id);
|
if path_to_local_id(let_expr, pat_hir_id);
|
||||||
// Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
|
// Ensure the `if let` statement is for the `Some` variant of `Option` or the `Ok` variant of `Result`
|
||||||
if let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind;
|
if let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind;
|
||||||
let some_ctor = is_lang_ctor(cx, qpath, OptionSome);
|
if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id);
|
||||||
let ok_ctor = is_lang_ctor(cx, qpath, ResultOk);
|
if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
|
||||||
|
let some_ctor = cx.tcx.lang_items().option_some_variant() == Some(variant_id);
|
||||||
|
let ok_ctor = cx.tcx.lang_items().result_ok_variant() == Some(variant_id);
|
||||||
if some_ctor || ok_ctor;
|
if some_ctor || ok_ctor;
|
||||||
// Ensure expr in `if let` is not used afterwards
|
// Ensure expr in `if let` is not used afterwards
|
||||||
if !is_local_used(cx, if_then, pat_hir_id);
|
if !is_local_used(cx, if_then, pat_hir_id);
|
||||||
|
@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
|||||||
use clippy_utils::higher;
|
use clippy_utils::higher;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
get_enclosing_loop_or_multi_call_closure, is_refutable, is_trait_method, match_def_path, paths,
|
get_enclosing_loop_or_multi_call_closure, is_refutable, is_res_lang_ctor, is_trait_method, visitors::is_res_used,
|
||||||
visitors::is_res_used,
|
|
||||||
};
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||||
use rustc_hir::{def::Res, Closure, Expr, ExprKind, HirId, Local, Mutability, PatKind, QPath, UnOp};
|
use rustc_hir::{def::Res, Closure, Expr, ExprKind, HirId, LangItem, Local, Mutability, PatKind, UnOp};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_middle::hir::nested_filter::OnlyBodies;
|
use rustc_middle::hir::nested_filter::OnlyBodies;
|
||||||
use rustc_middle::ty::adjustment::Adjust;
|
use rustc_middle::ty::adjustment::Adjust;
|
||||||
@ -19,9 +18,8 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
|
|||||||
let (scrutinee_expr, iter_expr_struct, iter_expr, some_pat, loop_expr) = if_chain! {
|
let (scrutinee_expr, iter_expr_struct, iter_expr, some_pat, loop_expr) = if_chain! {
|
||||||
if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr);
|
if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr);
|
||||||
// check for `Some(..)` pattern
|
// check for `Some(..)` pattern
|
||||||
if let PatKind::TupleStruct(QPath::Resolved(None, pat_path), some_pat, _) = let_pat.kind;
|
if let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind;
|
||||||
if let Res::Def(_, pat_did) = pat_path.res;
|
if is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome);
|
||||||
if match_def_path(cx, pat_did, &paths::OPTION_SOME);
|
|
||||||
// check for call to `Iterator::next`
|
// check for call to `Iterator::next`
|
||||||
if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
|
if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
|
||||||
if method_name.ident.name == sym::next;
|
if method_name.ident.name == sym::next;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::higher::IfLetOrMatch;
|
use clippy_utils::higher::IfLetOrMatch;
|
||||||
use clippy_utils::visitors::is_local_used;
|
use clippy_utils::visitors::is_local_used;
|
||||||
use clippy_utils::{is_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq};
|
use clippy_utils::{
|
||||||
|
is_res_lang_ctor, is_unit_expr, path_to_local, peel_blocks_with_stmt, peel_ref_operators, SpanlessEq,
|
||||||
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::MultiSpan;
|
use rustc_errors::MultiSpan;
|
||||||
use rustc_hir::LangItem::OptionNone;
|
use rustc_hir::LangItem::OptionNone;
|
||||||
@ -110,7 +112,7 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
|
|||||||
}
|
}
|
||||||
match arm.pat.kind {
|
match arm.pat.kind {
|
||||||
PatKind::Binding(..) | PatKind::Wild => true,
|
PatKind::Binding(..) | PatKind::Wild => true,
|
||||||
PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
|
PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
|||||||
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
|
use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
|
||||||
use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function};
|
use clippy_utils::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function};
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
can_move_expr_to_closure, is_else_clause, is_lang_ctor, is_lint_allowed, path_to_local_id, peel_blocks,
|
can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
|
||||||
peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
|
peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
|
||||||
};
|
};
|
||||||
use rustc_ast::util::parser::PREC_POSTFIX;
|
use rustc_ast::util::parser::PREC_POSTFIX;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -251,9 +251,11 @@ fn try_parse_pattern<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ctxt: Syn
|
|||||||
match pat.kind {
|
match pat.kind {
|
||||||
PatKind::Wild => Some(OptionPat::Wild),
|
PatKind::Wild => Some(OptionPat::Wild),
|
||||||
PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
|
PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
|
||||||
PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone) => Some(OptionPat::None),
|
PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionNone) => {
|
||||||
|
Some(OptionPat::None)
|
||||||
|
},
|
||||||
PatKind::TupleStruct(ref qpath, [pattern], _)
|
PatKind::TupleStruct(ref qpath, [pattern], _)
|
||||||
if is_lang_ctor(cx, qpath, OptionSome) && pat.span.ctxt() == ctxt =>
|
if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionSome) && pat.span.ctxt() == ctxt =>
|
||||||
{
|
{
|
||||||
Some(OptionPat::Some { pattern, ref_count })
|
Some(OptionPat::Some { pattern, ref_count })
|
||||||
},
|
},
|
||||||
@ -272,16 +274,14 @@ fn get_some_expr<'tcx>(
|
|||||||
) -> Option<SomeExpr<'tcx>> {
|
) -> Option<SomeExpr<'tcx>> {
|
||||||
// TODO: Allow more complex expressions.
|
// TODO: Allow more complex expressions.
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Call(
|
ExprKind::Call(callee, [arg])
|
||||||
Expr {
|
if ctxt == expr.span.ctxt() && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome) =>
|
||||||
kind: ExprKind::Path(ref qpath),
|
{
|
||||||
..
|
Some(SomeExpr {
|
||||||
},
|
expr: arg,
|
||||||
[arg],
|
needs_unsafe_block,
|
||||||
) if ctxt == expr.span.ctxt() && is_lang_ctor(cx, qpath, OptionSome) => Some(SomeExpr {
|
})
|
||||||
expr: arg,
|
},
|
||||||
needs_unsafe_block,
|
|
||||||
}),
|
|
||||||
ExprKind::Block(
|
ExprKind::Block(
|
||||||
Block {
|
Block {
|
||||||
stmts: [],
|
stmts: [],
|
||||||
@ -302,5 +302,5 @@ fn get_some_expr<'tcx>(
|
|||||||
|
|
||||||
// Checks for the `None` value.
|
// Checks for the `None` value.
|
||||||
fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
fn is_none_expr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
|
||||||
matches!(peel_blocks(expr).kind, ExprKind::Path(ref qpath) if is_lang_ctor(cx, qpath, OptionNone))
|
is_res_lang_ctor(cx, path_res(cx, peel_blocks(expr)), OptionNone)
|
||||||
}
|
}
|
||||||
|
@ -3,12 +3,14 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
|||||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::usage::contains_return_break_continue_macro;
|
use clippy_utils::usage::contains_return_break_continue_macro;
|
||||||
use clippy_utils::{is_lang_ctor, path_to_local_id, sugg};
|
use clippy_utils::{is_res_lang_ctor, path_to_local_id, sugg};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
|
use rustc_hir::LangItem::{OptionNone, ResultErr};
|
||||||
use rustc_hir::{Arm, Expr, PatKind};
|
use rustc_hir::{Arm, Expr, PatKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
|
use rustc_middle::ty::DefIdTree;
|
||||||
use rustc_span::sym;
|
use rustc_span::sym;
|
||||||
|
|
||||||
use super::MANUAL_UNWRAP_OR;
|
use super::MANUAL_UNWRAP_OR;
|
||||||
@ -59,15 +61,19 @@ fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<&'
|
|||||||
if arms.iter().all(|arm| arm.guard.is_none());
|
if arms.iter().all(|arm| arm.guard.is_none());
|
||||||
if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
|
if let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
|
||||||
match arm.pat.kind {
|
match arm.pat.kind {
|
||||||
PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
|
PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
|
||||||
PatKind::TupleStruct(ref qpath, [pat], _) =>
|
PatKind::TupleStruct(ref qpath, [pat], _) =>
|
||||||
matches!(pat.kind, PatKind::Wild) && is_lang_ctor(cx, qpath, ResultErr),
|
matches!(pat.kind, PatKind::Wild)
|
||||||
|
&& is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let unwrap_arm = &arms[1 - idx];
|
let unwrap_arm = &arms[1 - idx];
|
||||||
if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind;
|
if let PatKind::TupleStruct(ref qpath, [unwrap_pat], _) = unwrap_arm.pat.kind;
|
||||||
if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk);
|
if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, unwrap_arm.pat.hir_id);
|
||||||
|
if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
|
||||||
|
if cx.tcx.lang_items().option_some_variant() == Some(variant_id)
|
||||||
|
|| cx.tcx.lang_items().result_ok_variant() == Some(variant_id);
|
||||||
if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind;
|
if let PatKind::Binding(_, binding_hir_id, ..) = unwrap_pat.kind;
|
||||||
if path_to_local_id(unwrap_arm.body, binding_hir_id);
|
if path_to_local_id(unwrap_arm.body, binding_hir_id);
|
||||||
if cx.typeck_results().expr_adjustments(unwrap_arm.body).is_empty();
|
if cx.typeck_results().expr_adjustments(unwrap_arm.body).is_empty();
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::{is_lang_ctor, peel_blocks};
|
use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
|
use rustc_hir::{Arm, BindingAnnotation, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -59,18 +59,20 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
|
|||||||
|
|
||||||
// Checks if arm has the form `None => None`
|
// Checks if arm has the form `None => None`
|
||||||
fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
|
fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
|
||||||
matches!(arm.pat.kind, PatKind::Path(ref qpath) if is_lang_ctor(cx, qpath, LangItem::OptionNone))
|
matches!(
|
||||||
|
arm.pat.kind,
|
||||||
|
PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionNone)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
|
// Checks if arm has the form `Some(ref v) => Some(v)` (checks for `ref` and `ref mut`)
|
||||||
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
|
fn is_ref_some_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> Option<Mutability> {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind;
|
if let PatKind::TupleStruct(ref qpath, [first_pat, ..], _) = arm.pat.kind;
|
||||||
if is_lang_ctor(cx, qpath, LangItem::OptionSome);
|
if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionSome);
|
||||||
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind;
|
if let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., ident, _) = first_pat.kind;
|
||||||
if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind;
|
if let ExprKind::Call(e, [arg]) = peel_blocks(arm.body).kind;
|
||||||
if let ExprKind::Path(ref some_path) = e.kind;
|
if is_res_lang_ctor(cx, path_res(cx, e), LangItem::OptionSome);
|
||||||
if is_lang_ctor(cx, some_path, LangItem::OptionSome);
|
|
||||||
if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind;
|
if let ExprKind::Path(QPath::Resolved(_, path2)) = arg.kind;
|
||||||
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
|
if path2.segments.len() == 1 && ident.name == path2.segments[0].ident.name;
|
||||||
then {
|
then {
|
||||||
|
@ -3,7 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
|
|||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
|
use clippy_utils::ty::{is_type_diagnostic_item, same_type_and_consts};
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
eq_expr_value, get_parent_expr_for_hir, get_parent_node, higher, is_else_clause, is_lang_ctor, over,
|
eq_expr_value, get_parent_expr_for_hir, get_parent_node, higher, is_else_clause, is_res_lang_ctor, over, path_res,
|
||||||
peel_blocks_with_stmt,
|
peel_blocks_with_stmt,
|
||||||
};
|
};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -112,10 +112,7 @@ fn check_if_let_inner(cx: &LateContext<'_>, if_let: &higher::IfLet<'_>) -> bool
|
|||||||
let ret = strip_return(else_expr);
|
let ret = strip_return(else_expr);
|
||||||
let let_expr_ty = cx.typeck_results().expr_ty(if_let.let_expr);
|
let let_expr_ty = cx.typeck_results().expr_ty(if_let.let_expr);
|
||||||
if is_type_diagnostic_item(cx, let_expr_ty, sym::Option) {
|
if is_type_diagnostic_item(cx, let_expr_ty, sym::Option) {
|
||||||
if let ExprKind::Path(ref qpath) = ret.kind {
|
return is_res_lang_ctor(cx, path_res(cx, ret), OptionNone) || eq_expr_value(cx, if_let.let_expr, ret);
|
||||||
return is_lang_ctor(cx, qpath, OptionNone) || eq_expr_value(cx, if_let.let_expr, ret);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return eq_expr_value(cx, if_let.let_expr, ret);
|
return eq_expr_value(cx, if_let.let_expr, ret);
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,11 @@ use clippy_utils::source::snippet;
|
|||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
|
use clippy_utils::ty::{is_type_diagnostic_item, needs_ordered_drop};
|
||||||
use clippy_utils::visitors::any_temporaries_need_ordered_drop;
|
use clippy_utils::visitors::any_temporaries_need_ordered_drop;
|
||||||
use clippy_utils::{higher, is_lang_ctor, is_trait_method};
|
use clippy_utils::{higher, is_trait_method};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_ast::ast::LitKind;
|
use rustc_ast::ast::LitKind;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
|
use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
|
||||||
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
|
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -87,15 +88,21 @@ fn find_sugg_for_if_let<'tcx>(
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
PatKind::Path(ref path) => {
|
PatKind::Path(ref path) => {
|
||||||
let method = if is_lang_ctor(cx, path, OptionNone) {
|
if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(path, check_pat.hir_id)
|
||||||
"is_none()"
|
&& let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
|
||||||
} else if is_lang_ctor(cx, path, PollPending) {
|
{
|
||||||
"is_pending()"
|
let method = if cx.tcx.lang_items().option_none_variant() == Some(variant_id) {
|
||||||
|
"is_none()"
|
||||||
|
} else if cx.tcx.lang_items().poll_pending_variant() == Some(variant_id) {
|
||||||
|
"is_pending()"
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
// `None` and `Pending` don't have an inner type.
|
||||||
|
(method, cx.tcx.types.unit)
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
};
|
}
|
||||||
// `None` and `Pending` don't have an inner type.
|
|
||||||
(method, cx.tcx.types.unit)
|
|
||||||
},
|
},
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::{get_parent_expr, is_lang_ctor, match_def_path, paths};
|
use clippy_utils::{get_parent_expr, is_res_lang_ctor, match_def_path, path_res, paths};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::ResultErr;
|
use rustc_hir::LangItem::ResultErr;
|
||||||
@ -27,8 +27,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, scrutine
|
|||||||
if let ExprKind::Path(ref match_fun_path) = match_fun.kind;
|
if let ExprKind::Path(ref match_fun_path) = match_fun.kind;
|
||||||
if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..));
|
if matches!(match_fun_path, QPath::LangItem(LangItem::TryTraitBranch, ..));
|
||||||
if let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind;
|
if let ExprKind::Call(err_fun, [err_arg, ..]) = try_arg.kind;
|
||||||
if let ExprKind::Path(ref err_fun_path) = err_fun.kind;
|
if is_res_lang_ctor(cx, path_res(cx, err_fun), ResultErr);
|
||||||
if is_lang_ctor(cx, err_fun_path, ResultErr);
|
|
||||||
if let Some(return_ty) = find_return_type(cx, &expr.kind);
|
if let Some(return_ty) = find_return_type(cx, &expr.kind);
|
||||||
then {
|
then {
|
||||||
let prefix;
|
let prefix;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
|
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg, span_lint_and_then};
|
||||||
use clippy_utils::source::{snippet, snippet_with_applicability};
|
use clippy_utils::source::{snippet, snippet_with_applicability};
|
||||||
use clippy_utils::ty::is_non_aggregate_primitive_type;
|
use clippy_utils::ty::is_non_aggregate_primitive_type;
|
||||||
use clippy_utils::{is_default_equivalent, is_lang_ctor, meets_msrv, msrvs};
|
use clippy_utils::{is_default_equivalent, is_res_lang_ctor, meets_msrv, msrvs, path_res};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::OptionNone;
|
use rustc_hir::LangItem::OptionNone;
|
||||||
@ -102,40 +102,38 @@ impl_lint_pass!(MemReplace =>
|
|||||||
[MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]);
|
[MEM_REPLACE_OPTION_WITH_NONE, MEM_REPLACE_WITH_UNINIT, MEM_REPLACE_WITH_DEFAULT]);
|
||||||
|
|
||||||
fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
|
fn check_replace_option_with_none(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<'_>, expr_span: Span) {
|
||||||
if let ExprKind::Path(ref replacement_qpath) = src.kind {
|
// Check that second argument is `Option::None`
|
||||||
// Check that second argument is `Option::None`
|
if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
|
||||||
if is_lang_ctor(cx, replacement_qpath, OptionNone) {
|
// Since this is a late pass (already type-checked),
|
||||||
// Since this is a late pass (already type-checked),
|
// and we already know that the second argument is an
|
||||||
// and we already know that the second argument is an
|
// `Option`, we do not need to check the first
|
||||||
// `Option`, we do not need to check the first
|
// argument's type. All that's left is to get
|
||||||
// argument's type. All that's left is to get
|
// replacee's path.
|
||||||
// replacee's path.
|
let replaced_path = match dest.kind {
|
||||||
let replaced_path = match dest.kind {
|
ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => {
|
||||||
ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, replaced) => {
|
if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind {
|
||||||
if let ExprKind::Path(QPath::Resolved(None, replaced_path)) = replaced.kind {
|
replaced_path
|
||||||
replaced_path
|
} else {
|
||||||
} else {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
},
|
||||||
},
|
ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path,
|
||||||
ExprKind::Path(QPath::Resolved(None, replaced_path)) => replaced_path,
|
_ => return,
|
||||||
_ => return,
|
};
|
||||||
};
|
|
||||||
|
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
span_lint_and_sugg(
|
span_lint_and_sugg(
|
||||||
cx,
|
cx,
|
||||||
MEM_REPLACE_OPTION_WITH_NONE,
|
MEM_REPLACE_OPTION_WITH_NONE,
|
||||||
expr_span,
|
expr_span,
|
||||||
"replacing an `Option` with `None`",
|
"replacing an `Option` with `None`",
|
||||||
"consider `Option::take()` instead",
|
"consider `Option::take()` instead",
|
||||||
format!(
|
format!(
|
||||||
"{}.take()",
|
"{}.take()",
|
||||||
snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)
|
snippet_with_applicability(cx, replaced_path.span, "", &mut applicability)
|
||||||
),
|
),
|
||||||
applicability,
|
applicability,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,10 +201,8 @@ fn check_replace_with_default(cx: &LateContext<'_>, src: &Expr<'_>, dest: &Expr<
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// disable lint for Option since it is covered in another lint
|
// disable lint for Option since it is covered in another lint
|
||||||
if let ExprKind::Path(q) = &src.kind {
|
if is_res_lang_ctor(cx, path_res(cx, src), OptionNone) {
|
||||||
if is_lang_ctor(cx, q, OptionNone) {
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) {
|
if is_default_equivalent(cx, src) && !in_external_macro(cx.tcx.sess, expr_span) {
|
||||||
span_lint_and_then(
|
span_lint_and_then(
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::{get_expr_use_or_unification_node, is_lang_ctor, is_no_std_crate};
|
use clippy_utils::{get_expr_use_or_unification_node, is_no_std_crate, is_res_lang_ctor, path_res};
|
||||||
|
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||||
@ -26,26 +26,11 @@ impl IterType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) {
|
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'_>, method_name: &str, recv: &Expr<'_>) {
|
||||||
let item = match &recv.kind {
|
let item = match recv.kind {
|
||||||
ExprKind::Array(v) if v.len() <= 1 => v.first(),
|
ExprKind::Array([]) => None,
|
||||||
ExprKind::Path(p) => {
|
ExprKind::Array([e]) => Some(e),
|
||||||
if is_lang_ctor(cx, p, OptionNone) {
|
ExprKind::Path(ref p) if is_res_lang_ctor(cx, cx.qpath_res(p, recv.hir_id), OptionNone) => None,
|
||||||
None
|
ExprKind::Call(f, [arg]) if is_res_lang_ctor(cx, path_res(cx, f), OptionSome) => Some(arg),
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ExprKind::Call(f, some_args) if some_args.len() == 1 => {
|
|
||||||
if let ExprKind::Path(p) = &f.kind {
|
|
||||||
if is_lang_ctor(cx, p, OptionSome) {
|
|
||||||
Some(&some_args[0])
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
_ => return,
|
_ => return,
|
||||||
};
|
};
|
||||||
let iter_type = match method_name {
|
let iter_type = match method_name {
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
use clippy_utils::source::{indent_of, reindent_multiline, snippet_opt};
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::{is_lang_ctor, path_to_local_id};
|
use clippy_utils::{is_res_lang_ctor, path_res, path_to_local_id};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{ResultErr, ResultOk};
|
use rustc_hir::LangItem::{ResultErr, ResultOk};
|
||||||
use rustc_hir::{Closure, Expr, ExprKind, PatKind};
|
use rustc_hir::{Expr, ExprKind, PatKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
use rustc_span::symbol::sym;
|
use rustc_span::symbol::sym;
|
||||||
|
|
||||||
@ -22,8 +22,8 @@ pub(super) fn check<'tcx>(
|
|||||||
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
if let Some(method_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id);
|
||||||
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
|
if let Some(impl_id) = cx.tcx.impl_of_method(method_id);
|
||||||
if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Option);
|
if is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id), sym::Option);
|
||||||
if let ExprKind::Call(Expr { kind: ExprKind::Path(err_path), .. }, [err_arg]) = or_expr.kind;
|
if let ExprKind::Call(err_path, [err_arg]) = or_expr.kind;
|
||||||
if is_lang_ctor(cx, err_path, ResultErr);
|
if is_res_lang_ctor(cx, path_res(cx, err_path), ResultErr);
|
||||||
if is_ok_wrapping(cx, map_expr);
|
if is_ok_wrapping(cx, map_expr);
|
||||||
if let Some(recv_snippet) = snippet_opt(cx, recv.span);
|
if let Some(recv_snippet) = snippet_opt(cx, recv.span);
|
||||||
if let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span);
|
if let Some(err_arg_snippet) = snippet_opt(cx, err_arg.span);
|
||||||
@ -46,17 +46,19 @@ pub(super) fn check<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
|
fn is_ok_wrapping(cx: &LateContext<'_>, map_expr: &Expr<'_>) -> bool {
|
||||||
if let ExprKind::Path(ref qpath) = map_expr.kind {
|
match map_expr.kind {
|
||||||
if is_lang_ctor(cx, qpath, ResultOk) {
|
ExprKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, map_expr.hir_id), ResultOk) => true,
|
||||||
return true;
|
ExprKind::Closure(closure) => {
|
||||||
}
|
let body = cx.tcx.hir().body(closure.body);
|
||||||
}
|
if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind
|
||||||
if_chain! {
|
&& let ExprKind::Call(callee, [ok_arg]) = body.value.kind
|
||||||
if let ExprKind::Closure(&Closure { body, .. }) = map_expr.kind;
|
&& is_res_lang_ctor(cx, path_res(cx, callee), ResultOk)
|
||||||
let body = cx.tcx.hir().body(body);
|
{
|
||||||
if let PatKind::Binding(_, param_id, ..) = body.params[0].pat.kind;
|
path_to_local_id(ok_arg, param_id)
|
||||||
if let ExprKind::Call(Expr { kind: ExprKind::Path(ok_path), .. }, [ok_arg]) = body.value.kind;
|
} else {
|
||||||
if is_lang_ctor(cx, ok_path, ResultOk);
|
false
|
||||||
then { path_to_local_id(ok_arg, param_id) } else { false }
|
}
|
||||||
|
},
|
||||||
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::{is_lang_ctor, path_def_id};
|
use clippy_utils::{is_res_lang_ctor, path_def_id, path_res};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||||
@ -51,22 +51,12 @@ pub(super) fn check<'tcx>(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = def_arg.kind {
|
if !is_res_lang_ctor(cx, path_res(cx, def_arg), OptionNone) {
|
||||||
is_lang_ctor(cx, qpath, OptionNone)
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
if !default_arg_is_none {
|
|
||||||
// nothing to lint!
|
// nothing to lint!
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_arg.kind {
|
let f_arg_is_some = is_res_lang_ctor(cx, path_res(cx, map_arg), OptionSome);
|
||||||
is_lang_ctor(cx, qpath, OptionSome)
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
};
|
|
||||||
|
|
||||||
if is_option {
|
if is_option {
|
||||||
let self_snippet = snippet(cx, recv.span, "..");
|
let self_snippet = snippet(cx, recv.span, "..");
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::{diagnostics::span_lint_and_sugg, is_lang_ctor};
|
use clippy_utils::{diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::{lang_items::LangItem, Expr, ExprKind};
|
use rustc_hir::{lang_items::LangItem, Expr, ExprKind};
|
||||||
use rustc_lint::LateContext;
|
use rustc_lint::LateContext;
|
||||||
@ -58,8 +58,7 @@ pub(super) fn check<'tcx>(
|
|||||||
|
|
||||||
fn get_content_if_ctor_matches(cx: &LateContext<'_>, expr: &Expr<'_>, item: LangItem) -> Option<Span> {
|
fn get_content_if_ctor_matches(cx: &LateContext<'_>, expr: &Expr<'_>, item: LangItem) -> Option<Span> {
|
||||||
if let ExprKind::Call(some_expr, [arg]) = expr.kind
|
if let ExprKind::Call(some_expr, [arg]) = expr.kind
|
||||||
&& let ExprKind::Path(qpath) = &some_expr.kind
|
&& is_res_lang_ctor(cx, path_res(cx, some_expr), item)
|
||||||
&& is_lang_ctor(cx, qpath, item)
|
|
||||||
{
|
{
|
||||||
Some(arg.span)
|
Some(arg.span)
|
||||||
} else {
|
} else {
|
||||||
|
@ -2,7 +2,7 @@ use super::utils::clone_or_copy_needed;
|
|||||||
use clippy_utils::diagnostics::span_lint;
|
use clippy_utils::diagnostics::span_lint;
|
||||||
use clippy_utils::ty::is_copy;
|
use clippy_utils::ty::is_copy;
|
||||||
use clippy_utils::usage::mutated_variables;
|
use clippy_utils::usage::mutated_variables;
|
||||||
use clippy_utils::{is_lang_ctor, is_trait_method, path_to_local_id};
|
use clippy_utils::{is_res_lang_ctor, is_trait_method, path_res, path_to_local_id};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::intravisit::{walk_expr, Visitor};
|
use rustc_hir::intravisit::{walk_expr, Visitor};
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
use rustc_hir::LangItem::{OptionNone, OptionSome};
|
||||||
@ -61,15 +61,13 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, arg: &hir::Expr<
|
|||||||
|
|
||||||
// returns (found_mapping, found_filtering)
|
// returns (found_mapping, found_filtering)
|
||||||
fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> (bool, bool) {
|
fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tcx hir::Expr<'_>) -> (bool, bool) {
|
||||||
match &expr.kind {
|
match expr.kind {
|
||||||
hir::ExprKind::Call(func, args) => {
|
hir::ExprKind::Call(func, args) => {
|
||||||
if let hir::ExprKind::Path(ref path) = func.kind {
|
if is_res_lang_ctor(cx, path_res(cx, func), OptionSome) {
|
||||||
if is_lang_ctor(cx, path, OptionSome) {
|
if path_to_local_id(&args[0], arg_id) {
|
||||||
if path_to_local_id(&args[0], arg_id) {
|
return (false, false);
|
||||||
return (false, false);
|
|
||||||
}
|
|
||||||
return (true, false);
|
|
||||||
}
|
}
|
||||||
|
return (true, false);
|
||||||
}
|
}
|
||||||
(true, true)
|
(true, true)
|
||||||
},
|
},
|
||||||
@ -80,7 +78,7 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc
|
|||||||
hir::ExprKind::Match(_, arms, _) => {
|
hir::ExprKind::Match(_, arms, _) => {
|
||||||
let mut found_mapping = false;
|
let mut found_mapping = false;
|
||||||
let mut found_filtering = false;
|
let mut found_filtering = false;
|
||||||
for arm in *arms {
|
for arm in arms {
|
||||||
let (m, f) = check_expression(cx, arg_id, arm.body);
|
let (m, f) = check_expression(cx, arg_id, arm.body);
|
||||||
found_mapping |= m;
|
found_mapping |= m;
|
||||||
found_filtering |= f;
|
found_filtering |= f;
|
||||||
@ -93,7 +91,9 @@ fn check_expression<'tcx>(cx: &LateContext<'tcx>, arg_id: hir::HirId, expr: &'tc
|
|||||||
let else_check = check_expression(cx, arg_id, else_arm);
|
let else_check = check_expression(cx, arg_id, else_arm);
|
||||||
(if_check.0 | else_check.0, if_check.1 | else_check.1)
|
(if_check.0 | else_check.0, if_check.1 | else_check.1)
|
||||||
},
|
},
|
||||||
hir::ExprKind::Path(path) if is_lang_ctor(cx, path, OptionNone) => (false, true),
|
hir::ExprKind::Path(ref path) if is_res_lang_ctor(cx, cx.qpath_res(path, expr.hir_id), OptionNone) => {
|
||||||
|
(false, true)
|
||||||
|
},
|
||||||
_ => (true, true),
|
_ => (true, true),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::is_lang_ctor;
|
use clippy_utils::path_res;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::LangItem::{OptionSome, ResultOk};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::{AsyncGeneratorKind, Block, Body, Expr, ExprKind, GeneratorKind, LangItem, MatchSource, QPath};
|
use rustc_hir::{AsyncGeneratorKind, Block, Body, Expr, ExprKind, GeneratorKind, LangItem, MatchSource, QPath};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
|
use rustc_middle::ty::DefIdTree;
|
||||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||||
|
|
||||||
declare_clippy_lint! {
|
declare_clippy_lint! {
|
||||||
@ -112,11 +113,12 @@ impl LateLintPass<'_> for NeedlessQuestionMark {
|
|||||||
|
|
||||||
fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
fn check(cx: &LateContext<'_>, expr: &Expr<'_>) {
|
||||||
if_chain! {
|
if_chain! {
|
||||||
if let ExprKind::Call(path, [arg]) = &expr.kind;
|
if let ExprKind::Call(path, [arg]) = expr.kind;
|
||||||
if let ExprKind::Path(ref qpath) = &path.kind;
|
if let Res::Def(DefKind::Ctor(..), ctor_id) = path_res(cx, path);
|
||||||
let sugg_remove = if is_lang_ctor(cx, qpath, OptionSome) {
|
if let Some(variant_id) = cx.tcx.opt_parent(ctor_id);
|
||||||
|
let sugg_remove = if cx.tcx.lang_items().option_some_variant() == Some(variant_id) {
|
||||||
"Some()"
|
"Some()"
|
||||||
} else if is_lang_ctor(cx, qpath, ResultOk) {
|
} else if cx.tcx.lang_items().result_ok_variant() == Some(variant_id) {
|
||||||
"Ok()"
|
"Ok()"
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||||
use clippy_utils::sugg::Sugg;
|
use clippy_utils::sugg::Sugg;
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_lang_ctor, peel_blocks,
|
can_move_expr_to_closure, eager_or_lazy, higher, in_constant, is_else_clause, is_res_lang_ctor, peel_blocks,
|
||||||
peel_hir_expr_while, CaptureKind,
|
peel_hir_expr_while, CaptureKind,
|
||||||
};
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
@ -174,7 +174,8 @@ fn try_get_option_occurrence<'tcx>(
|
|||||||
|
|
||||||
fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'tcx Pat<'tcx>> {
|
fn try_get_inner_pat<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<&'tcx Pat<'tcx>> {
|
||||||
if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind {
|
if let PatKind::TupleStruct(ref qpath, [inner_pat], ..) = pat.kind {
|
||||||
if is_lang_ctor(cx, qpath, OptionSome) || is_lang_ctor(cx, qpath, ResultOk) {
|
let res = cx.qpath_res(qpath, pat.hir_id);
|
||||||
|
if is_res_lang_ctor(cx, res, OptionSome) || is_res_lang_ctor(cx, res, ResultOk) {
|
||||||
return Some(inner_pat);
|
return Some(inner_pat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -226,9 +227,10 @@ fn try_convert_match<'tcx>(
|
|||||||
|
|
||||||
fn is_none_or_err_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
|
fn is_none_or_err_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
|
||||||
match arm.pat.kind {
|
match arm.pat.kind {
|
||||||
PatKind::Path(ref qpath) => is_lang_ctor(cx, qpath, OptionNone),
|
PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
|
||||||
PatKind::TupleStruct(ref qpath, [first_pat], _) => {
|
PatKind::TupleStruct(ref qpath, [first_pat], _) => {
|
||||||
is_lang_ctor(cx, qpath, ResultErr) && matches!(first_pat.kind, PatKind::Wild)
|
is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr)
|
||||||
|
&& matches!(first_pat.kind, PatKind::Wild)
|
||||||
},
|
},
|
||||||
PatKind::Wild => true,
|
PatKind::Wild => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
diagnostics::span_lint_and_sugg, is_lang_ctor, peel_hir_expr_refs, peel_ref_operators, sugg,
|
diagnostics::span_lint_and_sugg, is_res_lang_ctor, path_res, peel_hir_expr_refs, peel_ref_operators, sugg,
|
||||||
ty::is_type_diagnostic_item,
|
ty::is_type_diagnostic_item,
|
||||||
};
|
};
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
@ -54,8 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for PartialeqToNone {
|
|||||||
// If the expression is a literal `Option::None`
|
// If the expression is a literal `Option::None`
|
||||||
let is_none_ctor = |expr: &Expr<'_>| {
|
let is_none_ctor = |expr: &Expr<'_>| {
|
||||||
!expr.span.from_expansion()
|
!expr.span.from_expansion()
|
||||||
&& matches!(&peel_hir_expr_refs(expr).0.kind,
|
&& is_res_lang_ctor(cx, path_res(cx, peel_hir_expr_refs(expr).0), LangItem::OptionNone)
|
||||||
ExprKind::Path(p) if is_lang_ctor(cx, p, LangItem::OptionNone))
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
|
@ -3,11 +3,12 @@ use clippy_utils::higher;
|
|||||||
use clippy_utils::source::snippet_with_applicability;
|
use clippy_utils::source::snippet_with_applicability;
|
||||||
use clippy_utils::ty::is_type_diagnostic_item;
|
use clippy_utils::ty::is_type_diagnostic_item;
|
||||||
use clippy_utils::{
|
use clippy_utils::{
|
||||||
eq_expr_value, get_parent_node, in_constant, is_else_clause, is_lang_ctor, path_to_local, path_to_local_id,
|
eq_expr_value, get_parent_node, in_constant, is_else_clause, is_res_lang_ctor, path_to_local, path_to_local_id,
|
||||||
peel_blocks, peel_blocks_with_stmt,
|
peel_blocks, peel_blocks_with_stmt,
|
||||||
};
|
};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
|
use rustc_hir::def::Res;
|
||||||
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
|
||||||
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
|
use rustc_hir::{BindingAnnotation, ByRef, Expr, ExprKind, Node, PatKind, PathSegment, QPath};
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
use rustc_lint::{LateContext, LateLintPass};
|
||||||
@ -58,7 +59,7 @@ enum IfBlockType<'hir> {
|
|||||||
/// Contains: let_pat_qpath (Xxx), let_pat_type, let_pat_sym (a), let_expr (b), if_then (c),
|
/// Contains: let_pat_qpath (Xxx), let_pat_type, let_pat_sym (a), let_expr (b), if_then (c),
|
||||||
/// if_else (d)
|
/// if_else (d)
|
||||||
IfLet(
|
IfLet(
|
||||||
&'hir QPath<'hir>,
|
Res,
|
||||||
Ty<'hir>,
|
Ty<'hir>,
|
||||||
Symbol,
|
Symbol,
|
||||||
&'hir Expr<'hir>,
|
&'hir Expr<'hir>,
|
||||||
@ -126,7 +127,14 @@ fn check_if_let_some_or_err_and_early_return<'tcx>(cx: &LateContext<'tcx>, expr:
|
|||||||
if ddpos.as_opt_usize().is_none();
|
if ddpos.as_opt_usize().is_none();
|
||||||
if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
|
if let PatKind::Binding(BindingAnnotation(by_ref, _), bind_id, ident, None) = field.kind;
|
||||||
let caller_ty = cx.typeck_results().expr_ty(let_expr);
|
let caller_ty = cx.typeck_results().expr_ty(let_expr);
|
||||||
let if_block = IfBlockType::IfLet(path1, caller_ty, ident.name, let_expr, if_then, if_else);
|
let if_block = IfBlockType::IfLet(
|
||||||
|
cx.qpath_res(path1, let_pat.hir_id),
|
||||||
|
caller_ty,
|
||||||
|
ident.name,
|
||||||
|
let_expr,
|
||||||
|
if_then,
|
||||||
|
if_else
|
||||||
|
);
|
||||||
if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
|
if (is_early_return(sym::Option, cx, &if_block) && path_to_local_id(peel_blocks(if_then), bind_id))
|
||||||
|| is_early_return(sym::Result, cx, &if_block);
|
|| is_early_return(sym::Result, cx, &if_block);
|
||||||
if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none();
|
if if_else.map(|e| eq_expr_value(cx, let_expr, peel_blocks(e))).filter(|e| *e).is_none();
|
||||||
@ -165,21 +173,21 @@ fn is_early_return(smbl: Symbol, cx: &LateContext<'_>, if_block: &IfBlockType<'_
|
|||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
IfBlockType::IfLet(qpath, let_expr_ty, let_pat_sym, let_expr, if_then, if_else) => {
|
IfBlockType::IfLet(res, let_expr_ty, let_pat_sym, let_expr, if_then, if_else) => {
|
||||||
is_type_diagnostic_item(cx, let_expr_ty, smbl)
|
is_type_diagnostic_item(cx, let_expr_ty, smbl)
|
||||||
&& match smbl {
|
&& match smbl {
|
||||||
sym::Option => {
|
sym::Option => {
|
||||||
// We only need to check `if let Some(x) = option` not `if let None = option`,
|
// We only need to check `if let Some(x) = option` not `if let None = option`,
|
||||||
// because the later one will be suggested as `if option.is_none()` thus causing conflict.
|
// because the later one will be suggested as `if option.is_none()` thus causing conflict.
|
||||||
is_lang_ctor(cx, qpath, OptionSome)
|
is_res_lang_ctor(cx, res, OptionSome)
|
||||||
&& if_else.is_some()
|
&& if_else.is_some()
|
||||||
&& expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, None)
|
&& expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, None)
|
||||||
},
|
},
|
||||||
sym::Result => {
|
sym::Result => {
|
||||||
(is_lang_ctor(cx, qpath, ResultOk)
|
(is_res_lang_ctor(cx, res, ResultOk)
|
||||||
&& if_else.is_some()
|
&& if_else.is_some()
|
||||||
&& expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, Some(let_pat_sym)))
|
&& expr_return_none_or_err(smbl, cx, if_else.unwrap(), let_expr, Some(let_pat_sym)))
|
||||||
|| is_lang_ctor(cx, qpath, ResultErr)
|
|| is_res_lang_ctor(cx, res, ResultErr)
|
||||||
&& expr_return_none_or_err(smbl, cx, if_then, let_expr, Some(let_pat_sym))
|
&& expr_return_none_or_err(smbl, cx, if_then, let_expr, Some(let_pat_sym))
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
@ -198,7 +206,7 @@ fn expr_return_none_or_err(
|
|||||||
match peel_blocks_with_stmt(expr).kind {
|
match peel_blocks_with_stmt(expr).kind {
|
||||||
ExprKind::Ret(Some(ret_expr)) => expr_return_none_or_err(smbl, cx, ret_expr, cond_expr, err_sym),
|
ExprKind::Ret(Some(ret_expr)) => expr_return_none_or_err(smbl, cx, ret_expr, cond_expr, err_sym),
|
||||||
ExprKind::Path(ref qpath) => match smbl {
|
ExprKind::Path(ref qpath) => match smbl {
|
||||||
sym::Option => is_lang_ctor(cx, qpath, OptionNone),
|
sym::Option => is_res_lang_ctor(cx, cx.qpath_res(qpath, expr.hir_id), OptionNone),
|
||||||
sym::Result => path_to_local(expr).is_some() && path_to_local(expr) == path_to_local(cond_expr),
|
sym::Result => path_to_local(expr).is_some() && path_to_local(expr) == path_to_local(cond_expr),
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use clippy_utils::source::snippet;
|
use clippy_utils::source::snippet;
|
||||||
use clippy_utils::{contains_return, is_lang_ctor, return_ty, visitors::find_all_ret_expressions};
|
use clippy_utils::{contains_return, is_res_lang_ctor, path_res, return_ty, visitors::find_all_ret_expressions};
|
||||||
use if_chain::if_chain;
|
use if_chain::if_chain;
|
||||||
use rustc_errors::Applicability;
|
use rustc_errors::Applicability;
|
||||||
use rustc_hir::intravisit::FnKind;
|
use rustc_hir::intravisit::FnKind;
|
||||||
@ -120,9 +120,7 @@ impl<'tcx> LateLintPass<'tcx> for UnnecessaryWraps {
|
|||||||
if !ret_expr.span.from_expansion();
|
if !ret_expr.span.from_expansion();
|
||||||
// Check if a function call.
|
// Check if a function call.
|
||||||
if let ExprKind::Call(func, [arg]) = ret_expr.kind;
|
if let ExprKind::Call(func, [arg]) = ret_expr.kind;
|
||||||
// Check if OPTION_SOME or RESULT_OK, depending on return type.
|
if is_res_lang_ctor(cx, path_res(cx, func), lang_item);
|
||||||
if let ExprKind::Path(qpath) = &func.kind;
|
|
||||||
if is_lang_ctor(cx, qpath, lang_item);
|
|
||||||
// Make sure the function argument does not contain a return expression.
|
// Make sure the function argument does not contain a return expression.
|
||||||
if !contains_return(arg);
|
if !contains_return(arg);
|
||||||
then {
|
then {
|
||||||
|
@ -238,17 +238,27 @@ pub fn in_constant(cx: &LateContext<'_>, id: HirId) -> bool {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if a `QPath` resolves to a constructor of a `LangItem`.
|
/// Checks if a `Res` refers to a constructor of a `LangItem`
|
||||||
/// For example, use this to check whether a function call or a pattern is `Some(..)`.
|
/// For example, use this to check whether a function call or a pattern is `Some(..)`.
|
||||||
pub fn is_lang_ctor(cx: &LateContext<'_>, qpath: &QPath<'_>, lang_item: LangItem) -> bool {
|
pub fn is_res_lang_ctor(cx: &LateContext<'_>, res: Res, lang_item: LangItem) -> bool {
|
||||||
if let QPath::Resolved(_, path) = qpath {
|
if let Res::Def(DefKind::Ctor(..), id) = res
|
||||||
if let Res::Def(DefKind::Ctor(..), ctor_id) = path.res {
|
&& let Ok(lang_id) = cx.tcx.lang_items().require(lang_item)
|
||||||
if let Ok(item_id) = cx.tcx.lang_items().require(lang_item) {
|
&& let Some(id) = cx.tcx.opt_parent(id)
|
||||||
return cx.tcx.parent(ctor_id) == item_id;
|
{
|
||||||
}
|
id == lang_id
|
||||||
}
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_res_diagnostic_ctor(cx: &LateContext<'_>, res: Res, diag_item: Symbol) -> bool {
|
||||||
|
if let Res::Def(DefKind::Ctor(..), id) = res
|
||||||
|
&& let Some(id) = cx.tcx.opt_parent(id)
|
||||||
|
{
|
||||||
|
cx.tcx.is_diagnostic_item(diag_item, id)
|
||||||
|
} else {
|
||||||
|
false
|
||||||
}
|
}
|
||||||
false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
|
pub fn is_unit_expr(expr: &Expr<'_>) -> bool {
|
||||||
@ -738,7 +748,7 @@ pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ExprKind::Call(repl_func, _) => is_default_equivalent_call(cx, repl_func),
|
ExprKind::Call(repl_func, _) => is_default_equivalent_call(cx, repl_func),
|
||||||
ExprKind::Path(qpath) => is_lang_ctor(cx, qpath, OptionNone),
|
ExprKind::Path(qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, e.hir_id), OptionNone),
|
||||||
ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
|
ExprKind::AddrOf(rustc_hir::BorrowKind::Ref, _, expr) => matches!(expr.kind, ExprKind::Array([])),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
@ -1553,7 +1563,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
|
|||||||
if_chain! {
|
if_chain! {
|
||||||
if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind;
|
if let PatKind::TupleStruct(ref path, pat, ddpos) = arm.pat.kind;
|
||||||
if ddpos.as_opt_usize().is_none();
|
if ddpos.as_opt_usize().is_none();
|
||||||
if is_lang_ctor(cx, path, ResultOk);
|
if is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultOk);
|
||||||
if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
|
if let PatKind::Binding(_, hir_id, _, None) = pat[0].kind;
|
||||||
if path_to_local_id(arm.body, hir_id);
|
if path_to_local_id(arm.body, hir_id);
|
||||||
then {
|
then {
|
||||||
@ -1565,7 +1575,7 @@ pub fn is_try<'tcx>(cx: &LateContext<'_>, expr: &'tcx Expr<'tcx>) -> Option<&'tc
|
|||||||
|
|
||||||
fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
|
fn is_err(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
|
||||||
if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
|
if let PatKind::TupleStruct(ref path, _, _) = arm.pat.kind {
|
||||||
is_lang_ctor(cx, path, ResultErr)
|
is_res_lang_ctor(cx, cx.qpath_res(path, arm.pat.hir_id), ResultErr)
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user