Eliminate PatKind::Path

This commit is contained in:
Oli Scherer
2024-12-12 10:37:37 +00:00
parent a4eff9d322
commit 7eefa7671f
18 changed files with 135 additions and 57 deletions

View File

@@ -56,7 +56,7 @@ fn unary_pattern(pat: &Pat<'_>) -> bool {
PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a),
PatKind::Ref(x, _) | PatKind::Box(x) | PatKind::Deref(x) | PatKind::Guard(x, _) => unary_pattern(x),
PatKind::Path(_) | PatKind::Expr(_) => true,
PatKind::Expr(_) => true,
}
}

View File

@@ -7,7 +7,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_lint_allowed, is_never_expr, msrvs, pat_and_expr_can_be_question_mark, peel_blocks};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind};
use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath, Stmt, StmtKind};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro;
@@ -292,7 +292,12 @@ fn pat_allowed_for_else(cx: &LateContext<'_>, pat: &'_ Pat<'_>, check_types: boo
// Only do the check if the type is "spelled out" in the pattern
if !matches!(
pat.kind,
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..)
PatKind::Struct(..)
| PatKind::TupleStruct(..)
| PatKind::Expr(PatExpr {
kind: PatExprKind::Path(..),
..
},)
) {
return;
}

View File

@@ -1,6 +1,6 @@
use rustc_errors::Applicability;
use rustc_hir::def::Res;
use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatKind, QPath};
use rustc_hir::{Arm, Expr, ExprKind, HirId, LangItem, MatchSource, Pat, PatExpr, PatExprKind, PatKind, QPath};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::GenericArgKind;
use rustc_session::declare_lint_pass;
@@ -68,7 +68,7 @@ fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<HirId> {
}
fn get_none<'tcx>(cx: &LateContext<'tcx>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> {
if let PatKind::Path(QPath::Resolved(_, path)) = arm.pat.kind
if let PatKind::Expr(PatExpr { kind: PatExprKind::Path(QPath::Resolved(_, path)), .. }) = arm.pat.kind
&& let Some(def_id) = path.res.opt_def_id()
// Since it comes from a pattern binding, we need to get the parent to actually match
// against it.

View File

@@ -8,7 +8,7 @@ use clippy_utils::{
};
use rustc_errors::MultiSpan;
use rustc_hir::LangItem::OptionNone;
use rustc_hir::{Arm, Expr, HirId, Pat, PatKind};
use rustc_hir::{Arm, Expr, HirId, Pat, PatExpr, PatExprKind, PatKind};
use rustc_lint::LateContext;
use rustc_span::Span;
@@ -119,7 +119,11 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
}
match arm.pat.kind {
PatKind::Binding(..) | PatKind::Wild => true,
PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(qpath),
hir_id,
..
}) => is_res_lang_ctor(cx, cx.qpath_res(qpath, *hir_id), OptionNone),
_ => false,
}
}

View File

@@ -6,7 +6,7 @@ use rustc_ast::BindingMode;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Arm, Expr, ExprKind, Pat, PatKind, Path, QPath};
use rustc_hir::{Arm, Expr, ExprKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath};
use rustc_lint::{LateContext, LintContext};
use rustc_middle::ty::Ty;
use rustc_span::symbol::Ident;
@@ -60,7 +60,16 @@ pub(crate) fn check_match(cx: &LateContext<'_>, expr: &Expr<'_>, scrutinee: &Exp
/// accepted.
fn is_variant_or_wildcard(cx: &LateContext<'_>, pat: &Pat<'_>, can_be_wild: bool, must_match_err: bool) -> bool {
match pat.kind {
PatKind::Wild | PatKind::Path(..) | PatKind::Binding(_, _, _, None) if can_be_wild => true,
PatKind::Wild
| PatKind::Expr(PatExpr {
kind: PatExprKind::Path(_),
..
})
| PatKind::Binding(_, _, _, None)
if can_be_wild =>
{
true
},
PatKind::TupleStruct(qpath, ..) => {
is_res_lang_ctor(cx, cx.qpath_res(&qpath, pat.hir_id), ResultErr) == must_match_err
},

View File

@@ -7,7 +7,7 @@ use clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, ResultErr};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Arm, Expr, Pat, PatKind};
use rustc_hir::{Arm, Expr, Pat, PatExpr, PatExprKind, PatKind};
use rustc_lint::LateContext;
use rustc_middle::ty::Ty;
use rustc_span::sym;
@@ -89,7 +89,11 @@ fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<(&
if arms.len() == 2
&& arms.iter().all(|arm| arm.guard.is_none())
&& let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| match arm.pat.kind {
PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
PatKind::Expr(PatExpr {
hir_id,
kind: PatExprKind::Path(qpath),
..
}) => is_res_lang_ctor(cx, cx.qpath_res(qpath, *hir_id), OptionNone),
PatKind::TupleStruct(ref qpath, [pat], _) => {
matches!(pat.kind, PatKind::Wild)
&& is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr)

View File

@@ -11,7 +11,7 @@ use rustc_ast::util::parser::ExprPrecedence;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::def::Res;
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath};
use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatExpr, PatExprKind, PatKind, Path, QPath};
use rustc_lint::LateContext;
use rustc_span::{SyntaxContext, sym};
@@ -256,9 +256,11 @@ pub(super) fn try_parse_pattern<'tcx>(
match pat.kind {
PatKind::Wild => Some(OptionPat::Wild),
PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionNone) => {
Some(OptionPat::None)
},
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(qpath),
hir_id,
..
}) if is_res_lang_ctor(cx, cx.qpath_res(qpath, *hir_id), OptionNone) => Some(OptionPat::None),
PatKind::TupleStruct(ref qpath, [pattern], _)
if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionSome) && pat.span.ctxt() == ctxt =>
{

View File

@@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::source::snippet_with_applicability;
use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks};
use rustc_errors::Applicability;
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatExpr, PatExprKind, PatKind, QPath};
use rustc_lint::LateContext;
use rustc_middle::ty;
@@ -59,7 +59,7 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr:
fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
matches!(
arm.pat.kind,
PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionNone)
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), .. }) if is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), LangItem::OptionNone)
)
}

View File

@@ -7,7 +7,7 @@ use rustc_arena::DroplessArena;
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::{Arm, Expr, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatExprKind, PatKind, RangeEnd};
use rustc_hir::{Arm, Expr, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatExpr, PatExprKind, PatKind, RangeEnd};
use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_lint::{LateContext, LintContext};
use rustc_middle::ty;
@@ -292,7 +292,11 @@ impl<'a> NormalizedPat<'a> {
Self::Tuple(var_id, pats)
},
PatKind::Or(pats) => Self::Or(arena.alloc_from_iter(pats.iter().map(|pat| Self::from_pat(cx, arena, pat)))),
PatKind::Path(ref path) => Self::Path(cx.qpath_res(path, pat.hir_id).opt_def_id()),
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(path),
hir_id,
..
}) => Self::Path(cx.qpath_res(path, *hir_id).opt_def_id()),
PatKind::Tuple(pats, wild_idx) => {
let field_count = match cx.typeck_results().pat_ty(pat).kind() {
ty::Tuple(subs) => subs.len(),

View File

@@ -3,7 +3,7 @@ use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::{is_refutable, peel_hir_pat_refs, recurse_or_patterns};
use rustc_errors::Applicability;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::{Arm, Expr, PatKind, PathSegment, QPath, Ty, TyKind};
use rustc_hir::{Arm, Expr, PatExpr, PatExprKind, PatKind, PathSegment, QPath, Ty, TyKind};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, VariantDef};
use rustc_span::sym;
@@ -60,8 +60,13 @@ pub(crate) fn check(cx: &LateContext<'_>, ex: &Expr<'_>, arms: &[Arm<'_>]) {
// covered by the set of guards that cover it, but that's really hard to do.
recurse_or_patterns(arm.pat, |pat| {
let path = match &peel_hir_pat_refs(pat).0.kind {
PatKind::Path(path) => {
let id = match cx.qpath_res(path, pat.hir_id) {
PatKind::Expr(PatExpr {
hir_id,
kind: PatExprKind::Path(path),
..
}) => {
// FIXME(clippy): don't you want to use the hir id of the peeled pat?
let id = match cx.qpath_res(path, *hir_id) {
Res::Def(
DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst,
_,

View File

@@ -8,7 +8,9 @@ use clippy_utils::{
};
use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionNone;
use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatExprKind, PatKind, Path, QPath};
use rustc_hir::{
Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatExpr, PatExprKind, PatKind, Path, QPath,
};
use rustc_lint::LateContext;
use rustc_span::sym;
@@ -183,7 +185,13 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
return !matches!(annot, BindingMode(ByRef::Yes(_), _)) && pat_ident.name == first_seg.ident.name;
},
// Example: `Custom::TypeA => Custom::TypeB`, or `None => None`
(PatKind::Path(QPath::Resolved(_, p_path)), ExprKind::Path(QPath::Resolved(_, e_path))) => {
(
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(QPath::Resolved(_, p_path)),
..
}),
ExprKind::Path(QPath::Resolved(_, e_path)),
) => {
return over(p_path.segments, e_path.segments, |p_seg, e_seg| {
p_seg.ident.name == e_seg.ident.name
});

View File

@@ -9,7 +9,7 @@ use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
use rustc_hir::def::{DefKind, Res};
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatExprKind, PatKind, QPath, UnOp};
use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, UnOp};
use rustc_lint::LateContext;
use rustc_middle::ty::{self, GenericArgKind, Ty};
use rustc_span::{Span, Symbol, sym};
@@ -149,8 +149,12 @@ fn find_method_and_type<'tcx>(
None
}
},
PatKind::Path(ref path) => {
if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(path, check_pat.hir_id)
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(path),
hir_id,
..
}) => {
if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(path, *hir_id)
&& let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
{
let method = if cx.tcx.lang_items().option_none_variant() == Some(variant_id) {
@@ -351,10 +355,20 @@ fn found_good_method<'tcx>(
None
}
},
(PatKind::TupleStruct(path_left, patterns, _), PatKind::Path(path_right))
| (PatKind::Path(path_left), PatKind::TupleStruct(path_right, patterns, _))
if patterns.len() == 1 =>
{
(
PatKind::TupleStruct(path_left, patterns, _),
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(path_right),
..
}),
)
| (
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(path_left),
..
}),
PatKind::TupleStruct(path_right, patterns, _),
) if patterns.len() == 1 => {
if let PatKind::Wild = patterns[0].kind {
find_good_method_for_match(
cx,
@@ -389,7 +403,13 @@ fn found_good_method<'tcx>(
None
}
},
(PatKind::Path(path_left), PatKind::Wild) => get_good_method(cx, arms, path_left),
(
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(path_left),
..
}),
PatKind::Wild,
) => get_good_method(cx, arms, path_left),
_ => None,
}
}

View File

@@ -114,7 +114,7 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
}
let (pat, pat_ref_count) = peel_hir_pat_refs(arm.pat);
let (msg, sugg) = if let PatKind::Path(_) | PatKind::Expr(_) = pat.kind
let (msg, sugg) = if let PatKind::Expr(_) = pat.kind
&& let (ty, ty_ref_count) = peel_middle_ty_refs(cx.typeck_results().expr_ty(ex))
&& let Some(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait()
&& let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait()
@@ -331,14 +331,16 @@ impl<'a> PatState<'a> {
#[expect(clippy::similar_names)]
fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool {
match pat.kind {
PatKind::Path(_)
if match *cx.typeck.pat_ty(pat).peel_refs().kind() {
ty::Adt(adt, _) => adt.is_enum() || (adt.is_struct() && !adt.non_enum_variant().fields.is_empty()),
ty::Tuple(tys) => !tys.is_empty(),
ty::Array(_, len) => len.try_to_target_usize(cx.tcx) != Some(1),
ty::Slice(..) => true,
_ => false,
} =>
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(_),
..
}) if match *cx.typeck.pat_ty(pat).peel_refs().kind() {
ty::Adt(adt, _) => adt.is_enum() || (adt.is_struct() && !adt.non_enum_variant().fields.is_empty()),
ty::Tuple(tys) => !tys.is_empty(),
ty::Array(_, len) => len.try_to_target_usize(cx.tcx) != Some(1),
ty::Slice(..) => true,
_ => false,
} =>
{
matches!(self, Self::Wild)
},
@@ -386,7 +388,6 @@ impl<'a> PatState<'a> {
| PatKind::Binding(_, _, _, None)
| PatKind::Expr(_)
| PatKind::Range(..)
| PatKind::Path(_)
| PatKind::Never
| PatKind::Err(_) => {
*self = PatState::Wild;

View File

@@ -7,7 +7,9 @@ use clippy_utils::{
use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
use rustc_hir::def::Res;
use rustc_hir::{Arm, BindingMode, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath, UnOp};
use rustc_hir::{
Arm, BindingMode, Expr, ExprKind, MatchSource, Mutability, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, UnOp,
};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass;
use rustc_span::SyntaxContext;
@@ -281,7 +283,11 @@ fn try_convert_match<'tcx>(
fn is_none_or_err_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
match arm.pat.kind {
PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(qpath),
hir_id,
..
}) => is_res_lang_ctor(cx, cx.qpath_res(qpath, *hir_id), OptionNone),
PatKind::TupleStruct(ref qpath, [first_pat], _) => {
is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr)
&& matches!(first_pat.kind, PatKind::Wild)

View File

@@ -10,7 +10,7 @@ use rustc_hir::def_id::LocalDefId;
use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
use rustc_hir::{
self as hir, AmbigArg, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind,
HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
HirId, Impl, ImplItemKind, Item, ItemKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath, Ty, TyKind,
};
use rustc_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass};
@@ -258,7 +258,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
&& self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
&& let Some(&StackItem::Check { impl_id, .. }) = self.stack.last()
// get the path from the pattern
&& let PatKind::Path(QPath::Resolved(_, path))
&& let PatKind::Expr(&PatExpr { kind: PatExprKind::Path(QPath::Resolved(_, path)), .. })
| PatKind::TupleStruct(QPath::Resolved(_, path), _, _)
| PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind
&& cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).instantiate_identity()

View File

@@ -708,11 +708,6 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
self.qpath(qpath);
self.slice(fields, |pat| self.pat(pat));
},
PatKind::Path(ref qpath) => {
bind!(self, qpath);
kind!("Path(ref {qpath})");
self.qpath(qpath);
},
PatKind::Tuple(fields, skip_pos) => {
bind!(self, fields);
kind!("Tuple({fields}, {skip_pos:?})");

View File

@@ -524,7 +524,6 @@ impl HirEqInterExpr<'_, '_, '_> {
}
eq
},
(PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r),
(&PatKind::Expr(l), &PatKind::Expr(r)) => self.eq_pat_expr(l, r),
(&PatKind::Tuple(l, ls), &PatKind::Tuple(r, rs)) => ls == rs && over(l, r, |l, r| self.eq_pat(l, r)),
(&PatKind::Range(ref ls, ref le, li), &PatKind::Range(ref rs, ref re, ri)) => {
@@ -1120,7 +1119,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
self.hash_pat(pat);
}
},
PatKind::Path(ref qpath) => self.hash_qpath(qpath),
PatKind::Range(s, e, i) => {
if let Some(s) = s {
self.hash_pat_expr(s);

View File

@@ -106,8 +106,8 @@ use rustc_hir::{
self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef,
TyKind, UnOp, def,
PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind,
TraitItemRef, TraitRef, TyKind, UnOp, def,
};
use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -560,7 +560,20 @@ macro_rules! maybe_path {
};
}
maybe_path!(Expr, ExprKind);
maybe_path!(Pat, PatKind);
impl<'hir> MaybePath<'hir> for Pat<'hir> {
fn hir_id(&self) -> HirId {
self.hir_id
}
fn qpath_opt(&self) -> Option<&QPath<'hir>> {
match &self.kind {
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(qpath),
..
}) => Some(qpath),
_ => None,
}
}
}
maybe_path!(Ty, TyKind);
/// If `maybe_path` is a path node, resolves it, otherwise returns `Res::Err`
@@ -1753,7 +1766,11 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)),
PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
PatKind::Expr(PatExpr {
kind: PatExprKind::Path(qpath),
hir_id,
..
}) => is_enum_variant(cx, qpath, *hir_id),
PatKind::Or(pats) => {
// TODO: should be the honest check, that pats is exhaustive set
are_refutable(cx, pats)