Skip to content

Commit

Permalink
Auto merge of #7962 - Jarcho:fix_match_type_on_diagnostic_items, r=ll…
Browse files Browse the repository at this point in the history
…ogiq

Fix and improve `match_type_on_diagnostic_item`

This extracts the fix for the lint out of #7647. There's still a couple of other functions to check, but at least this will get lint working again.

The two added util functions (`is_diagnostic_item` and `is_lang_item`) are needed to handle `DefId` for unit and tuple struct/variant constructors. The `rustc_diagnostic_item` and `lang` attributes are attached to the struct/variant `DefId`, but most of the time they are used through their constructors which have a different `DefId`. The two utility functions will check if the `DefId` is for a constructor and switch to the associated struct/variant `DefId`.

There does seem to be a bug on rustc's side where constructor `DefId`s from external crates seem to be returning `DefKind::Variant` instead of `DefKind::Ctor()`. There's a workaround put in right.

changelog: None
  • Loading branch information
bors committed Oct 2, 2022
2 parents 0341198 + 162aa19 commit bef93d3
Show file tree
Hide file tree
Showing 48 changed files with 735 additions and 374 deletions.
8 changes: 4 additions & 4 deletions clippy_lints/src/await_holding_invalid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use rustc_hir::{def::Res, AsyncGeneratorKind, Body, BodyId, GeneratorKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::GeneratorInteriorTypeCause;
use rustc_session::{declare_tool_lint, impl_lint_pass};
use rustc_span::Span;
use rustc_span::{sym, Span};

use crate::utils::conf::DisallowedType;

Expand Down Expand Up @@ -276,9 +276,9 @@ fn emit_invalid_type(cx: &LateContext<'_>, span: Span, disallowed: &DisallowedTy
}

fn is_mutex_guard(cx: &LateContext<'_>, def_id: DefId) -> bool {
match_def_path(cx, def_id, &paths::MUTEX_GUARD)
|| match_def_path(cx, def_id, &paths::RWLOCK_READ_GUARD)
|| match_def_path(cx, def_id, &paths::RWLOCK_WRITE_GUARD)
cx.tcx.is_diagnostic_item(sym::MutexGuard, def_id)
|| cx.tcx.is_diagnostic_item(sym::RwLockReadGuard, def_id)
|| cx.tcx.is_diagnostic_item(sym::RwLockWriteGuard, def_id)
|| match_def_path(cx, def_id, &paths::PARKING_LOT_MUTEX_GUARD)
|| match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_READ_GUARD)
|| match_def_path(cx, def_id, &paths::PARKING_LOT_RWLOCK_WRITE_GUARD)
Expand Down
10 changes: 5 additions & 5 deletions clippy_lints/src/if_then_some_else_none.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::eager_or_lazy::switch_to_eager_eval;
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::{Expr, ExprKind, Stmt, StmtKind};
use rustc_lint::{LateContext, LateLintPass, LintContext};
Expand Down Expand Up @@ -76,10 +78,8 @@ impl<'tcx> LateLintPass<'tcx> for IfThenSomeElseNone {
&& let ExprKind::Block(then_block, _) = then.kind
&& let Some(then_expr) = then_block.expr
&& let ExprKind::Call(then_call, [then_arg]) = then_expr.kind
&& let ExprKind::Path(ref then_call_qpath) = then_call.kind
&& is_lang_ctor(cx, then_call_qpath, OptionSome)
&& let ExprKind::Path(ref qpath) = peel_blocks(els).kind
&& is_lang_ctor(cx, qpath, OptionNone)
&& is_res_lang_ctor(cx, path_res(cx, then_call), OptionSome)
&& is_res_lang_ctor(cx, path_res(cx, peel_blocks(els)), OptionNone)
&& !stmts_contains_early_return(then_block.stmts)
{
let cond_snip = snippet_with_macro_callsite(cx, cond.span, "[condition]");
Expand Down
15 changes: 11 additions & 4 deletions clippy_lints/src/infinite_iter.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint;
use clippy_utils::higher;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{higher, match_def_path, path_def_id, paths};
use rustc_hir::{BorrowKind, Closure, Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
Expand Down Expand Up @@ -168,9 +168,16 @@ 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, _) => path_def_id(cx, path)
.map_or(false, |id| match_def_path(cx, id, &paths::ITER_REPEAT))
.into(),
ExprKind::Call(path, _) => {
if let ExprKind::Path(ref qpath) = path.kind {
cx.qpath_res(qpath, path.hir_id)
.opt_def_id()
.map_or(false, |id| cx.tcx.is_diagnostic_item(sym::iter_repeat, id))
.into()
} else {
Finite
}
},
ExprKind::Struct(..) => higher::Range::hir(expr).map_or(false, |r| r.end.is_none()).into(),
_ => Finite,
}
Expand Down
7 changes: 5 additions & 2 deletions clippy_lints/src/inherent_to_string.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use clippy_utils::diagnostics::span_lint_and_help;
use clippy_utils::ty::{implements_trait, is_type_diagnostic_item};
use clippy_utils::{get_trait_def_id, paths, return_ty, trait_ref_of_method};
use clippy_utils::{return_ty, trait_ref_of_method};
use if_chain::if_chain;
use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind};
use rustc_lint::{LateContext, LateLintPass};
Expand Down Expand Up @@ -118,7 +118,10 @@ impl<'tcx> LateLintPass<'tcx> for InherentToString {
}

fn show_lint(cx: &LateContext<'_>, item: &ImplItem<'_>) {
let display_trait_id = get_trait_def_id(cx, &paths::DISPLAY_TRAIT).expect("Failed to get trait ID of `Display`!");
let display_trait_id = cx
.tcx
.get_diagnostic_item(sym::Display)
.expect("Failed to get trait ID of `Display`!");

// Get the real type of 'self'
let self_type = cx.tcx.fn_sig(item.def_id).input(0);
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/lib.register_internal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ store.register_group(true, "clippy::internal", Some("clippy_internal"), vec![
LintId::of(utils::internal_lints::INVALID_CLIPPY_VERSION_ATTRIBUTE),
LintId::of(utils::internal_lints::INVALID_PATHS),
LintId::of(utils::internal_lints::LINT_WITHOUT_LINT_PASS),
LintId::of(utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM),
LintId::of(utils::internal_lints::MISSING_CLIPPY_VERSION_ATTRIBUTE),
LintId::of(utils::internal_lints::MISSING_MSRV_ATTR_IMPL),
LintId::of(utils::internal_lints::OUTER_EXPN_EXPN_DATA),
LintId::of(utils::internal_lints::PRODUCE_ICE),
LintId::of(utils::internal_lints::UNNECESSARY_DEF_PATH),
LintId::of(utils::internal_lints::UNNECESSARY_SYMBOL_STR),
])
4 changes: 2 additions & 2 deletions clippy_lints/src/lib.register_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@ store.register_lints(&[
#[cfg(feature = "internal")]
utils::internal_lints::LINT_WITHOUT_LINT_PASS,
#[cfg(feature = "internal")]
utils::internal_lints::MATCH_TYPE_ON_DIAGNOSTIC_ITEM,
#[cfg(feature = "internal")]
utils::internal_lints::MISSING_CLIPPY_VERSION_ATTRIBUTE,
#[cfg(feature = "internal")]
utils::internal_lints::MISSING_MSRV_ATTR_IMPL,
Expand All @@ -34,6 +32,8 @@ store.register_lints(&[
#[cfg(feature = "internal")]
utils::internal_lints::PRODUCE_ICE,
#[cfg(feature = "internal")]
utils::internal_lints::UNNECESSARY_DEF_PATH,
#[cfg(feature = "internal")]
utils::internal_lints::UNNECESSARY_SYMBOL_STR,
almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE,
approx_const::APPROX_CONSTANT,
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(|_| Box::new(utils::internal_lints::InvalidPaths));
store.register_late_pass(|_| Box::<utils::internal_lints::InterningDefinedSymbol>::default());
store.register_late_pass(|_| Box::<utils::internal_lints::LintWithoutLintPass>::default());
store.register_late_pass(|_| Box::new(utils::internal_lints::MatchTypeOnDiagItem));
store.register_late_pass(|_| Box::new(utils::internal_lints::UnnecessaryDefPath));
store.register_late_pass(|_| Box::new(utils::internal_lints::OuterExpnDataPass));
store.register_late_pass(|_| Box::new(utils::internal_lints::MsrvAttrImpl));
}
Expand Down
9 changes: 4 additions & 5 deletions clippy_lints/src/loops/manual_find.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use super::utils::make_iterator_snippet;
use super::MANUAL_FIND;
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,
};
use if_chain::if_chain;
Expand Down Expand Up @@ -30,8 +30,8 @@ pub(super) fn check<'tcx>(
if let [stmt] = block.stmts;
if let StmtKind::Semi(semi) = stmt.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 is_lang_ctor(cx, ctor, LangItem::OptionSome);
if let ExprKind::Call(ctor, [inner_ret]) = ret_value.kind;
if is_res_lang_ctor(cx, path_res(cx, ctor), LangItem::OptionSome);
if path_res(cx, inner_ret) == Res::Local(binding_id);
if let Some((last_stmt, last_ret)) = last_stmt_and_ret(cx, expr);
then {
Expand Down Expand Up @@ -143,8 +143,7 @@ fn last_stmt_and_ret<'tcx>(
if let Some((_, Node::Block(block))) = parent_iter.next();
if let Some((last_stmt, last_ret)) = extract(block);
if last_stmt.hir_id == node_hir;
if let ExprKind::Path(path) = &last_ret.kind;
if is_lang_ctor(cx, path, LangItem::OptionNone);
if is_res_lang_ctor(cx, path_res(cx, last_ret), LangItem::OptionNone);
if let Some((_, Node::Expr(_block))) = parent_iter.next();
// This includes the function header
if let Some((_, func)) = parent_iter.next();
Expand Down
12 changes: 7 additions & 5 deletions clippy_lints/src/loops/manual_flatten.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ use super::MANUAL_FLATTEN;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher;
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 rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionSome, ResultOk};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Expr, Pat, PatKind};
use rustc_lint::LateContext;
use rustc_middle::ty;
use rustc_middle::ty::{self, DefIdTree};
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
Expand All @@ -30,8 +30,10 @@ pub(super) fn check<'tcx>(
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`
if let PatKind::TupleStruct(ref qpath, _, _) = let_pat.kind;
let some_ctor = is_lang_ctor(cx, qpath, OptionSome);
let ok_ctor = is_lang_ctor(cx, qpath, ResultOk);
if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(qpath, let_pat.hir_id);
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;
// Ensure expr in `if let` is not used afterwards
if !is_local_used(cx, if_then, pat_hir_id);
Expand Down
10 changes: 4 additions & 6 deletions clippy_lints/src/loops/while_let_on_iterator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,12 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::higher;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{
get_enclosing_loop_or_multi_call_closure, is_refutable, is_trait_method, match_def_path, paths,
visitors::is_res_used,
get_enclosing_loop_or_multi_call_closure, is_refutable, is_res_lang_ctor, is_trait_method, visitors::is_res_used,
};
use if_chain::if_chain;
use rustc_errors::Applicability;
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_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::ty::adjustment::Adjust;
Expand All @@ -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! {
if let Some(higher::WhileLet { if_then, let_pat, let_expr }) = higher::WhileLet::hir(expr);
// check for `Some(..)` pattern
if let PatKind::TupleStruct(QPath::Resolved(None, pat_path), some_pat, _) = let_pat.kind;
if let Res::Def(_, pat_did) = pat_path.res;
if match_def_path(cx, pat_did, &paths::OPTION_SOME);
if let PatKind::TupleStruct(ref pat_path, some_pat, _) = let_pat.kind;
if is_res_lang_ctor(cx, cx.qpath_res(pat_path, let_pat.hir_id), LangItem::OptionSome);
// check for call to `Iterator::next`
if let ExprKind::MethodCall(method_name, iter_expr, [], _) = let_expr.kind;
if method_name.ident.name == sym::next;
Expand Down
2 changes: 1 addition & 1 deletion clippy_lints/src/manual_retain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ fn check_into_iter(
&& match_def_path(cx, filter_def_id, &paths::CORE_ITER_FILTER)
&& let hir::ExprKind::MethodCall(_, struct_expr, [], _) = &into_iter_expr.kind
&& let Some(into_iter_def_id) = cx.typeck_results().type_dependent_def_id(into_iter_expr.hir_id)
&& match_def_path(cx, into_iter_def_id, &paths::CORE_ITER_INTO_ITER)
&& cx.tcx.lang_items().require(hir::LangItem::IntoIterIntoIter).ok() == Some(into_iter_def_id)
&& match_acceptable_type(cx, left_expr, msrv)
&& SpanlessEq::new(cx).eq_expr(left_expr, struct_expr) {
suggest(cx, parent_expr, left_expr, target_expr);
Expand Down
6 changes: 4 additions & 2 deletions clippy_lints/src/matches/collapsible_match.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::higher::IfLetOrMatch;
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 rustc_errors::MultiSpan;
use rustc_hir::LangItem::OptionNone;
Expand Down Expand Up @@ -110,7 +112,7 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
}
match arm.pat.kind {
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,
}
}
Expand Down
30 changes: 15 additions & 15 deletions clippy_lints/src/matches/manual_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::ty::{is_type_diagnostic_item, peel_mid_ty_refs_is_mutable, type_is_unsafe_function};
use clippy_utils::{
can_move_expr_to_closure, is_else_clause, is_lang_ctor, is_lint_allowed, path_to_local_id, peel_blocks,
peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
can_move_expr_to_closure, is_else_clause, is_lint_allowed, is_res_lang_ctor, path_res, path_to_local_id,
peel_blocks, peel_hir_expr_refs, peel_hir_expr_while, CaptureKind,
};
use rustc_ast::util::parser::PREC_POSTFIX;
use rustc_errors::Applicability;
Expand Down Expand Up @@ -251,9 +251,11 @@ fn try_parse_pattern<'tcx>(cx: &LateContext<'tcx>, pat: &'tcx Pat<'_>, ctxt: Syn
match pat.kind {
PatKind::Wild => Some(OptionPat::Wild),
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], _)
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 })
},
Expand All @@ -272,16 +274,14 @@ fn get_some_expr<'tcx>(
) -> Option<SomeExpr<'tcx>> {
// TODO: Allow more complex expressions.
match expr.kind {
ExprKind::Call(
Expr {
kind: ExprKind::Path(ref qpath),
..
},
[arg],
) if ctxt == expr.span.ctxt() && is_lang_ctor(cx, qpath, OptionSome) => Some(SomeExpr {
expr: arg,
needs_unsafe_block,
}),
ExprKind::Call(callee, [arg])
if ctxt == expr.span.ctxt() && is_res_lang_ctor(cx, path_res(cx, callee), OptionSome) =>
{
Some(SomeExpr {
expr: arg,
needs_unsafe_block,
})
},
ExprKind::Block(
Block {
stmts: [],
Expand All @@ -302,5 +302,5 @@ fn get_some_expr<'tcx>(

// Checks for the `None` value.
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)
}
16 changes: 11 additions & 5 deletions clippy_lints/src/matches/manual_unwrap_or.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::ty::is_type_diagnostic_item;
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 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_lint::LateContext;
use rustc_middle::ty::DefIdTree;
use rustc_span::sym;

use super::MANUAL_UNWRAP_OR;
Expand Down Expand Up @@ -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 let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| {
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], _) =>
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,
}
});
let unwrap_arm = &arms[1 - idx];
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 path_to_local_id(unwrap_arm.body, binding_hir_id);
if cx.typeck_results().expr_adjustments(unwrap_arm.body).is_empty();
Expand Down
Loading

0 comments on commit bef93d3

Please sign in to comment.