Auto merge of #134248 - oli-obk:patkind-path-removal, r=BoxyUwU

Merge `PatKind::Path` into `PatKind::Expr`

Follow-up to #134228

We always had a duplication where `Path`s could be represented as `PatKind::Path` or `PatKind::Lit(ExprKind::Path)`. We had to handle both everywhere, and still do after #134228, so I'm removing it now.
This commit is contained in:
bors 2025-01-29 19:16:29 +00:00
commit ae5de6c759
42 changed files with 299 additions and 183 deletions

View file

@ -1391,7 +1391,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
None, None,
); );
// Destructure like a unit struct. // Destructure like a unit struct.
let unit_struct_pat = hir::PatKind::Path(qpath); let unit_struct_pat = hir::PatKind::Expr(self.arena.alloc(hir::PatExpr {
kind: hir::PatExprKind::Path(qpath),
hir_id: self.next_id(),
span: self.lower_span(lhs.span),
}));
return self.pat_without_dbm(lhs.span, unit_struct_pat); return self.pat_without_dbm(lhs.span, unit_struct_pat);
} }
} }

View file

@ -69,7 +69,16 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
ImplTraitContext::Disallowed(ImplTraitPosition::Path), ImplTraitContext::Disallowed(ImplTraitPosition::Path),
None, None,
); );
break hir::PatKind::Path(qpath); let kind = hir::PatExprKind::Path(qpath);
let span = self.lower_span(pattern.span);
let expr = hir::PatExpr { hir_id: pat_hir_id, span, kind };
let expr = self.arena.alloc(expr);
return hir::Pat {
hir_id: self.next_id(),
kind: hir::PatKind::Expr(expr),
span,
default_binding_modes: true,
};
} }
PatKind::Struct(qself, path, fields, etc) => { PatKind::Struct(qself, path, fields, etc) => {
let qpath = self.lower_qpath( let qpath = self.lower_qpath(
@ -304,16 +313,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
) )
} }
Some(res) => { Some(res) => {
let hir_id = self.next_id();
let res = self.lower_res(res); let res = self.lower_res(res);
hir::PatKind::Path(hir::QPath::Resolved( let span = self.lower_span(ident.span);
hir::PatKind::Expr(self.arena.alloc(hir::PatExpr {
kind: hir::PatExprKind::Path(hir::QPath::Resolved(
None, None,
self.arena.alloc(hir::Path { self.arena.alloc(hir::Path {
span: self.lower_span(ident.span), span,
res, res,
segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), self.next_id(), res)],
}), }),
)) )),
hir_id: self.next_id(),
span,
}))
} }
} }
} }

View file

@ -1437,7 +1437,7 @@ impl<'hir> Pat<'hir> {
use PatKind::*; use PatKind::*;
match self.kind { match self.kind {
Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true, Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => true,
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it), Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_short_(it),
Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)), Struct(_, fields, _) => fields.iter().all(|field| field.pat.walk_short_(it)),
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().all(|p| p.walk_short_(it)),
@ -1464,7 +1464,7 @@ impl<'hir> Pat<'hir> {
use PatKind::*; use PatKind::*;
match self.kind { match self.kind {
Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {} Wild | Never | Expr(_) | Range(..) | Binding(.., None) | Err(_) => {}
Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it), Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(s)) | Guard(s, _) => s.walk_(it),
Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)), Struct(_, fields, _) => fields.iter().for_each(|field| field.pat.walk_(it)),
TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)), TupleStruct(_, s, _) | Tuple(s, _) | Or(s) => s.iter().for_each(|p| p.walk_(it)),
@ -1618,9 +1618,6 @@ pub enum PatKind<'hir> {
/// A never pattern `!`. /// A never pattern `!`.
Never, Never,
/// A path pattern for a unit struct/variant or a (maybe-associated) constant.
Path(QPath<'hir>),
/// A tuple pattern (e.g., `(a, b)`). /// A tuple pattern (e.g., `(a, b)`).
/// If the `..` pattern fragment is present, then `Option<usize>` denotes its position. /// If the `..` pattern fragment is present, then `Option<usize>` denotes its position.
/// `0 <= position <= subpats.len()` /// `0 <= position <= subpats.len()`

View file

@ -709,9 +709,6 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span)); try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
walk_list!(visitor, visit_pat, children); walk_list!(visitor, visit_pat, children);
} }
PatKind::Path(ref qpath) => {
try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
}
PatKind::Struct(ref qpath, fields, _) => { PatKind::Struct(ref qpath, fields, _) => {
try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span)); try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span));
walk_list!(visitor, visit_pat_field, fields); walk_list!(visitor, visit_pat_field, fields);

View file

@ -105,7 +105,10 @@ impl hir::Pat<'_> {
let mut variants = vec![]; let mut variants = vec![];
self.walk(|p| match &p.kind { self.walk(|p| match &p.kind {
PatKind::Or(_) => false, PatKind::Or(_) => false,
PatKind::Path(hir::QPath::Resolved(_, path)) PatKind::Expr(hir::PatExpr {
kind: hir::PatExprKind::Path(hir::QPath::Resolved(_, path)),
..
})
| PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..) | PatKind::TupleStruct(hir::QPath::Resolved(_, path), ..)
| PatKind::Struct(hir::QPath::Resolved(_, path), ..) => { | PatKind::Struct(hir::QPath::Resolved(_, path), ..) => {
if let Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), id) = if let Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), id) =

View file

@ -703,7 +703,6 @@ fn resolve_local<'tcx>(
| PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..) | PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)
| PatKind::Wild | PatKind::Wild
| PatKind::Never | PatKind::Never
| PatKind::Path(_)
| PatKind::Expr(_) | PatKind::Expr(_)
| PatKind::Range(_, _, _) | PatKind::Range(_, _, _)
| PatKind::Err(_) => false, | PatKind::Err(_) => false,

View file

@ -41,8 +41,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)), kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)),
.. ..
}) })
| hir::Node::Pat(hir::Pat { | hir::Node::PatExpr(hir::PatExpr {
kind: hir::PatKind::Path(hir::QPath::TypeRelative(qself, _)), kind: hir::PatExprKind::Path(hir::QPath::TypeRelative(qself, _)),
.. ..
}) if qself.hir_id == self_ty.hir_id => true, }) if qself.hir_id == self_ty.hir_id => true,
_ => false, _ => false,

View file

@ -1906,9 +1906,6 @@ impl<'a> State<'a> {
} }
self.pclose(); self.pclose();
} }
PatKind::Path(ref qpath) => {
self.print_qpath(qpath, true);
}
PatKind::Struct(ref qpath, fields, etc) => { PatKind::Struct(ref qpath, fields, etc) => {
self.print_qpath(qpath, true); self.print_qpath(qpath, true);
self.nbsp(); self.nbsp();

View file

@ -480,7 +480,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::PatKind::Binding(_, _, _, _) hir::PatKind::Binding(_, _, _, _)
| hir::PatKind::Struct(_, _, _) | hir::PatKind::Struct(_, _, _)
| hir::PatKind::TupleStruct(_, _, _) | hir::PatKind::TupleStruct(_, _, _)
| hir::PatKind::Path(_)
| hir::PatKind::Tuple(_, _) | hir::PatKind::Tuple(_, _)
| hir::PatKind::Box(_) | hir::PatKind::Box(_)
| hir::PatKind::Ref(_, _) | hir::PatKind::Ref(_, _)

View file

@ -11,10 +11,9 @@ use hir::def::DefKind;
use hir::pat_util::EnumerateAndAdjustIterator as _; use hir::pat_util::EnumerateAndAdjustIterator as _;
use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, Res}; use rustc_hir::def::{CtorOf, Res};
use rustc_hir::def_id::LocalDefId; use rustc_hir::def_id::LocalDefId;
use rustc_hir::{HirId, PatKind}; use rustc_hir::{self as hir, HirId, PatExpr, PatExprKind, PatKind};
use rustc_lint::LateContext; use rustc_lint::LateContext;
use rustc_middle::hir::place::ProjectionKind; use rustc_middle::hir::place::ProjectionKind;
// Export these here so that Clippy can use them. // Export these here so that Clippy can use them.
@ -564,11 +563,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
// FIXME(never_patterns): does this do what I expect? // FIXME(never_patterns): does this do what I expect?
needs_to_be_read = true; needs_to_be_read = true;
} }
PatKind::Path(qpath) => { PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, span }) => {
// A `Path` pattern is just a name like `Foo`. This is either a // A `Path` pattern is just a name like `Foo`. This is either a
// named constant or else it refers to an ADT variant // named constant or else it refers to an ADT variant
let res = self.cx.typeck_results().qpath_res(qpath, pat.hir_id); let res = self.cx.typeck_results().qpath_res(qpath, *hir_id);
match res { match res {
Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => {
// Named constants have to be equated with the value // Named constants have to be equated with the value
@ -581,7 +580,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
// Otherwise, this is a struct/enum variant, and so it's // Otherwise, this is a struct/enum variant, and so it's
// only a read if we need to read the discriminant. // only a read if we need to read the discriminant.
needs_to_be_read |= needs_to_be_read |=
self.is_multivariant_adt(place.place.ty(), pat.span); self.is_multivariant_adt(place.place.ty(), *span);
} }
} }
} }
@ -1801,8 +1800,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
} }
} }
PatKind::Path(_) PatKind::Binding(.., None)
| PatKind::Binding(.., None)
| PatKind::Expr(..) | PatKind::Expr(..)
| PatKind::Range(..) | PatKind::Range(..)
| PatKind::Never | PatKind::Never

View file

@ -5,12 +5,12 @@ use hir::def_id::LocalDefId;
use rustc_ast::util::parser::ExprPrecedence; use rustc_ast::util::parser::ExprPrecedence;
use rustc_data_structures::packed::Pu128; use rustc_data_structures::packed::Pu128;
use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_errors::{Applicability, Diag, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res};
use rustc_hir::lang_items::LangItem; use rustc_hir::lang_items::LangItem;
use rustc_hir::{ use rustc_hir::{
Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, self as hir, Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind,
Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind, expr_needs_parens, GenericBound, HirId, Node, PatExpr, PatExprKind, Path, QPath, Stmt, StmtKind, TyKind,
WherePredicateKind, expr_needs_parens,
}; };
use rustc_hir_analysis::collect::suggest_impl_trait; use rustc_hir_analysis::collect::suggest_impl_trait;
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
@ -1422,8 +1422,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// since the user probably just misunderstood how `let else` // since the user probably just misunderstood how `let else`
// and `&&` work together. // and `&&` work together.
if let Some((_, hir::Node::LetStmt(local))) = cond_parent if let Some((_, hir::Node::LetStmt(local))) = cond_parent
&& let hir::PatKind::Path(qpath) | hir::PatKind::TupleStruct(qpath, _, _) = && let hir::PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), .. })
&local.pat.kind | hir::PatKind::TupleStruct(qpath, _, _) = &local.pat.kind
&& let hir::QPath::Resolved(None, path) = qpath && let hir::QPath::Resolved(None, path) = qpath
&& let Some(did) = path && let Some(did) = path
.res .res

View file

@ -177,8 +177,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}) })
| hir::Node::Pat(&hir::Pat { | hir::Node::Pat(&hir::Pat {
kind: kind:
hir::PatKind::Path(QPath::TypeRelative(rcvr, segment)) hir::PatKind::Struct(QPath::TypeRelative(rcvr, segment), ..)
| hir::PatKind::Struct(QPath::TypeRelative(rcvr, segment), ..)
| hir::PatKind::TupleStruct(QPath::TypeRelative(rcvr, segment), ..), | hir::PatKind::TupleStruct(QPath::TypeRelative(rcvr, segment), ..),
span, span,
.. ..

View file

@ -11,8 +11,8 @@ use rustc_errors::{
use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::pat_util::EnumerateAndAdjustIterator;
use rustc_hir::{ use rustc_hir::{
self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatKind, self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatExpr,
expr_needs_parens, PatExprKind, PatKind, expr_needs_parens,
}; };
use rustc_infer::infer; use rustc_infer::infer;
use rustc_middle::traits::PatternOriginExpr; use rustc_middle::traits::PatternOriginExpr;
@ -312,9 +312,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'_, 'tcx>) { fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'_, 'tcx>) {
let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info; let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
let path_res = match &pat.kind { let path_res = match pat.kind {
PatKind::Path(qpath) => { PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref qpath), hir_id, span }) => {
Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span)) Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span))
} }
_ => None, _ => None,
}; };
@ -333,6 +333,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PatKind::Wild | PatKind::Err(_) => expected, PatKind::Wild | PatKind::Err(_) => expected,
// We allow any type here; we ensure that the type is uninhabited during match checking. // We allow any type here; we ensure that the type is uninhabited during match checking.
PatKind::Never => expected, PatKind::Never => expected,
PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref qpath), hir_id, span }) => {
let ty = self.check_pat_path(
*hir_id,
pat.hir_id,
*span,
qpath,
path_res.unwrap(),
expected,
ti,
);
self.write_ty(*hir_id, ty);
ty
}
PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, ti), PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
PatKind::Binding(ba, var_id, ident, sub) => { PatKind::Binding(ba, var_id, ident, sub) => {
@ -341,9 +354,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PatKind::TupleStruct(ref qpath, subpats, ddpos) => { PatKind::TupleStruct(ref qpath, subpats, ddpos) => {
self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info) self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
} }
PatKind::Path(ref qpath) => {
self.check_pat_path(pat.hir_id, pat.span, qpath, path_res.unwrap(), expected, ti)
}
PatKind::Struct(ref qpath, fields, has_rest_pat) => { PatKind::Struct(ref qpath, fields, has_rest_pat) => {
self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info) self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info)
} }
@ -456,16 +466,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
| PatKind::Slice(..) => AdjustMode::Peel, | PatKind::Slice(..) => AdjustMode::Peel,
// A never pattern behaves somewhat like a literal or unit variant. // A never pattern behaves somewhat like a literal or unit variant.
PatKind::Never => AdjustMode::Peel, PatKind::Never => AdjustMode::Peel,
// String and byte-string literals result in types `&str` and `&[u8]` respectively. PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => match opt_path_res.unwrap() {
// All other literals result in non-reference types.
// As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
//
// Call `resolve_vars_if_possible` here for inline const blocks.
PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
ty::Ref(..) => AdjustMode::Pass,
_ => AdjustMode::Peel,
},
PatKind::Path(_) => match opt_path_res.unwrap() {
// These constants can be of a reference type, e.g. `const X: &u8 = &0;`. // These constants can be of a reference type, e.g. `const X: &u8 = &0;`.
// Peeling the reference types too early will cause type checking failures. // Peeling the reference types too early will cause type checking failures.
// Although it would be possible to *also* peel the types of the constants too. // Although it would be possible to *also* peel the types of the constants too.
@ -476,6 +477,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// a reference type wherefore peeling doesn't give up any expressiveness. // a reference type wherefore peeling doesn't give up any expressiveness.
_ => AdjustMode::Peel, _ => AdjustMode::Peel,
}, },
// String and byte-string literals result in types `&str` and `&[u8]` respectively.
// All other literals result in non-reference types.
// As a result, we allow `if let 0 = &&0 {}` but not `if let "foo" = &&"foo" {}`.
//
// Call `resolve_vars_if_possible` here for inline const blocks.
PatKind::Expr(lt) => match self.resolve_vars_if_possible(self.check_pat_expr_unadjusted(lt)).kind() {
ty::Ref(..) => AdjustMode::Pass,
_ => AdjustMode::Peel,
},
// Ref patterns are complicated, we handle them in `check_pat_ref`. // Ref patterns are complicated, we handle them in `check_pat_ref`.
PatKind::Ref(..) => AdjustMode::Pass, PatKind::Ref(..) => AdjustMode::Pass,
// A `_` pattern works with any expected type, so there's no need to do anything. // A `_` pattern works with any expected type, so there's no need to do anything.
@ -1001,7 +1013,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
PatKind::Wild PatKind::Wild
| PatKind::Never | PatKind::Never
| PatKind::Binding(..) | PatKind::Binding(..)
| PatKind::Path(..)
| PatKind::Box(..) | PatKind::Box(..)
| PatKind::Deref(_) | PatKind::Deref(_)
| PatKind::Ref(..) | PatKind::Ref(..)
@ -1139,7 +1150,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn check_pat_path( fn check_pat_path(
&self, &self,
hir_id: HirId, path_id: HirId,
pat_id_for_diag: HirId,
span: Span, span: Span,
qpath: &hir::QPath<'_>, qpath: &hir::QPath<'_>,
path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]), path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
@ -1193,11 +1205,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Type-check the path. // Type-check the path.
let (pat_ty, pat_res) = let (pat_ty, pat_res) =
self.instantiate_value_path(segments, opt_ty, res, span, span, hir_id); self.instantiate_value_path(segments, opt_ty, res, span, span, path_id);
if let Err(err) = if let Err(err) =
self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty) self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty)
{ {
self.emit_bad_pat_path(err, hir_id, span, res, pat_res, pat_ty, segments); self.emit_bad_pat_path(err, pat_id_for_diag, span, res, pat_res, pat_ty, segments);
} }
pat_ty pat_ty
} }

View file

@ -6,7 +6,7 @@ use rustc_hir::def::Res;
use rustc_hir::def_id::DefId; use rustc_hir::def_id::DefId;
use rustc_hir::{ use rustc_hir::{
AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, AmbigArg, BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat,
PatKind, Path, PathSegment, QPath, Ty, TyKind, PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Ty, TyKind,
}; };
use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy}; use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -164,11 +164,9 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
TyKind::Path(QPath::Resolved(_, path)) => { TyKind::Path(QPath::Resolved(_, path)) => {
if lint_ty_kind_usage(cx, &path.res) { if lint_ty_kind_usage(cx, &path.res) {
let span = match cx.tcx.parent_hir_node(ty.hir_id) { let span = match cx.tcx.parent_hir_node(ty.hir_id) {
Node::Pat(Pat { Node::PatExpr(PatExpr { kind: PatExprKind::Path(qpath), .. })
kind: | Node::Pat(Pat {
PatKind::Path(qpath) kind: PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..),
| PatKind::TupleStruct(qpath, ..)
| PatKind::Struct(qpath, ..),
.. ..
}) })
| Node::Expr( | Node::Expr(

View file

@ -1,7 +1,7 @@
use rustc_abi::ExternAbi; use rustc_abi::ExternAbi;
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::intravisit::FnKind; use rustc_hir::intravisit::FnKind;
use rustc_hir::{AttrArgs, AttrItem, AttrKind, GenericParamKind, PatKind}; use rustc_hir::{AttrArgs, AttrItem, AttrKind, GenericParamKind, PatExprKind, PatKind};
use rustc_middle::ty; use rustc_middle::ty;
use rustc_session::config::CrateType; use rustc_session::config::CrateType;
use rustc_session::{declare_lint, declare_lint_pass}; use rustc_session::{declare_lint, declare_lint_pass};
@ -527,7 +527,11 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) { fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
// Lint for constants that look like binding identifiers (#7526) // Lint for constants that look like binding identifiers (#7526)
if let PatKind::Path(hir::QPath::Resolved(None, path)) = p.kind { if let PatKind::Expr(hir::PatExpr {
kind: PatExprKind::Path(hir::QPath::Resolved(None, path)),
..
}) = p.kind
{
if let Res::Def(DefKind::Const, _) = path.res { if let Res::Def(DefKind::Const, _) = path.res {
if let [segment] = path.segments { if let [segment] = path.segments {
NonUpperCaseGlobals::check_upper_case( NonUpperCaseGlobals::check_upper_case(

View file

@ -332,10 +332,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
.unwrap_or_else(PatKind::Error) .unwrap_or_else(PatKind::Error)
} }
hir::PatKind::Path(ref qpath) => {
return self.lower_path(qpath, pat.hir_id, pat.span);
}
hir::PatKind::Deref(subpattern) => { hir::PatKind::Deref(subpattern) => {
let mutable = self.typeck_results.pat_has_ref_mut_binding(subpattern); let mutable = self.typeck_results.pat_has_ref_mut_binding(subpattern);
let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };

View file

@ -10,11 +10,10 @@ use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
use rustc_abi::FieldIdx; use rustc_abi::FieldIdx;
use rustc_data_structures::unord::UnordSet; use rustc_data_structures::unord::UnordSet;
use rustc_errors::MultiSpan; use rustc_errors::MultiSpan;
use rustc_hir as hir;
use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def::{CtorOf, DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{Node, PatKind, TyKind}; use rustc_hir::{self as hir, Node, PatKind, TyKind};
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::middle::privacy::Level; use rustc_middle::middle::privacy::Level;
use rustc_middle::query::Providers; use rustc_middle::query::Providers;
@ -637,10 +636,6 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
let res = self.typeck_results().qpath_res(path, pat.hir_id); let res = self.typeck_results().qpath_res(path, pat.hir_id);
self.handle_field_pattern_match(pat, res, fields); self.handle_field_pattern_match(pat, res, fields);
} }
PatKind::Path(ref qpath) => {
let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
self.handle_res(res);
}
PatKind::TupleStruct(ref qpath, fields, dotdot) => { PatKind::TupleStruct(ref qpath, fields, dotdot) => {
let res = self.typeck_results().qpath_res(qpath, pat.hir_id); let res = self.typeck_results().qpath_res(qpath, pat.hir_id);
self.handle_tuple_field_pattern_match(pat, res, fields, dotdot); self.handle_tuple_field_pattern_match(pat, res, fields, dotdot);
@ -652,6 +647,17 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'tcx> {
self.in_pat = false; self.in_pat = false;
} }
fn visit_pat_expr(&mut self, expr: &'tcx rustc_hir::PatExpr<'tcx>) {
match &expr.kind {
rustc_hir::PatExprKind::Path(qpath) => {
let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
self.handle_res(res);
}
_ => {}
}
intravisit::walk_pat_expr(self, expr);
}
fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) { fn visit_path(&mut self, path: &hir::Path<'tcx>, _: hir::HirId) {
self.handle_res(path.res); self.handle_res(path.res);
intravisit::walk_path(self, path); intravisit::walk_path(self, path);

View file

@ -298,7 +298,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
TupleStruct, TupleStruct,
Or, Or,
Never, Never,
Path,
Tuple, Tuple,
Box, Box,
Deref, Deref,

View file

@ -303,7 +303,8 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
return kw::Underscore; return kw::Underscore;
} }
PatKind::Binding(_, _, ident, _) => return ident.name, PatKind::Binding(_, _, ident, _) => return ident.name,
PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), PatKind::TupleStruct(ref p, ..)
| PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref p), .. }) => qpath_to_string(p),
PatKind::Or(pats) => { PatKind::Or(pats) => {
pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ") pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ")
} }

View file

@ -4,7 +4,9 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_hir::def::{DefKind, Res}; use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::intravisit::{self, Visitor};
use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, Pat, PatKind, QPath}; use rustc_hir::{
ExprKind, HirId, Item, ItemKind, Mod, Node, Pat, PatExpr, PatExprKind, PatKind, QPath,
};
use rustc_middle::hir::nested_filter; use rustc_middle::hir::nested_filter;
use rustc_middle::ty::TyCtxt; use rustc_middle::ty::TyCtxt;
use rustc_span::hygiene::MacroKind; use rustc_span::hygiene::MacroKind;
@ -191,17 +193,21 @@ impl SpanMapVisitor<'_> {
} }
fn handle_pat(&mut self, p: &Pat<'_>) { fn handle_pat(&mut self, p: &Pat<'_>) {
match p.kind { let mut check_qpath = |qpath, hir_id| match qpath {
PatKind::Binding(_, _, _, Some(p)) => self.handle_pat(p),
PatKind::Struct(qpath, _, _)
| PatKind::TupleStruct(qpath, _, _)
| PatKind::Path(qpath) => match qpath {
QPath::TypeRelative(_, path) if matches!(path.res, Res::Err) => { QPath::TypeRelative(_, path) if matches!(path.res, Res::Err) => {
self.infer_id(path.hir_id, Some(p.hir_id), qpath.span()); self.infer_id(path.hir_id, Some(hir_id), qpath.span());
} }
QPath::Resolved(_, path) => self.handle_path(path), QPath::Resolved(_, path) => self.handle_path(path),
_ => {} _ => {}
}, };
match p.kind {
PatKind::Binding(_, _, _, Some(p)) => self.handle_pat(p),
PatKind::Struct(qpath, _, _) | PatKind::TupleStruct(qpath, _, _) => {
check_qpath(qpath, p.hir_id)
}
PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), hir_id, .. }) => {
check_qpath(*qpath, *hir_id)
}
PatKind::Or(pats) => { PatKind::Or(pats) => {
for pat in pats { for pat in pats {
self.handle_pat(pat); self.handle_pat(pat);

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::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::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::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 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_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_errors::Applicability; 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_lint::{LateContext, LintContext};
use rustc_middle::lint::in_external_macro; 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 // Only do the check if the type is "spelled out" in the pattern
if !matches!( if !matches!(
pat.kind, pat.kind,
PatKind::Struct(..) | PatKind::TupleStruct(..) | PatKind::Path(..) PatKind::Struct(..)
| PatKind::TupleStruct(..)
| PatKind::Expr(PatExpr {
kind: PatExprKind::Path(..),
..
},)
) { ) {
return; return;
} }

View file

@ -1,6 +1,6 @@
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::Res; 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_lint::{LateContext, LateLintPass, LintContext};
use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::GenericArgKind;
use rustc_session::declare_lint_pass; 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>> { 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() && 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 // Since it comes from a pattern binding, we need to get the parent to actually match
// against it. // against it.

View file

@ -8,7 +8,7 @@ use clippy_utils::{
}; };
use rustc_errors::MultiSpan; use rustc_errors::MultiSpan;
use rustc_hir::LangItem::OptionNone; 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_lint::LateContext;
use rustc_span::Span; use rustc_span::Span;
@ -119,7 +119,11 @@ 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_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, _ => false,
} }
} }

View file

@ -6,7 +6,7 @@ use rustc_ast::BindingMode;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr};
use rustc_hir::def::{DefKind, Res}; 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_lint::{LateContext, LintContext};
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_span::symbol::Ident; use rustc_span::symbol::Ident;
@ -60,7 +60,16 @@ pub(crate) fn check_match(cx: &LateContext<'_>, expr: &Expr<'_>, scrutinee: &Exp
/// accepted. /// accepted.
fn is_variant_or_wildcard(cx: &LateContext<'_>, pat: &Pat<'_>, can_be_wild: bool, must_match_err: bool) -> bool { fn is_variant_or_wildcard(cx: &LateContext<'_>, pat: &Pat<'_>, can_be_wild: bool, must_match_err: bool) -> bool {
match pat.kind { 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, ..) => { PatKind::TupleStruct(qpath, ..) => {
is_res_lang_ctor(cx, cx.qpath_res(&qpath, pat.hir_id), ResultErr) == must_match_err 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_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, ResultErr}; use rustc_hir::LangItem::{OptionNone, ResultErr};
use rustc_hir::def::{DefKind, Res}; 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_lint::LateContext;
use rustc_middle::ty::Ty; use rustc_middle::ty::Ty;
use rustc_span::sym; use rustc_span::sym;
@ -89,7 +89,11 @@ fn applicable_or_arm<'a>(cx: &LateContext<'_>, arms: &'a [Arm<'a>]) -> Option<(&
if arms.len() == 2 if arms.len() == 2
&& arms.iter().all(|arm| arm.guard.is_none()) && arms.iter().all(|arm| arm.guard.is_none())
&& let Some((idx, or_arm)) = arms.iter().enumerate().find(|(_, arm)| match arm.pat.kind { && 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], _) => { PatKind::TupleStruct(ref qpath, [pat], _) => {
matches!(pat.kind, PatKind::Wild) matches!(pat.kind, PatKind::Wild)
&& is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr) && 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_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome}; use rustc_hir::LangItem::{OptionNone, OptionSome};
use rustc_hir::def::Res; 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_lint::LateContext;
use rustc_span::{SyntaxContext, sym}; use rustc_span::{SyntaxContext, sym};
@ -256,9 +256,11 @@ pub(super) fn try_parse_pattern<'tcx>(
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_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionNone) => { PatKind::Expr(PatExpr {
Some(OptionPat::None) 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], _) PatKind::TupleStruct(ref qpath, [pattern], _)
if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionSome) && pat.span.ctxt() == ctxt => 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::source::snippet_with_applicability;
use clippy_utils::{is_res_lang_ctor, path_res, 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, 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_lint::LateContext;
use rustc_middle::ty; 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 { fn is_none_arm(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
matches!( matches!(
arm.pat.kind, 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_ast::ast::LitKind;
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def_id::DefId; 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::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
use rustc_lint::{LateContext, LintContext}; use rustc_lint::{LateContext, LintContext};
use rustc_middle::ty; use rustc_middle::ty;
@ -292,7 +292,11 @@ impl<'a> NormalizedPat<'a> {
Self::Tuple(var_id, pats) 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::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) => { PatKind::Tuple(pats, wild_idx) => {
let field_count = match cx.typeck_results().pat_ty(pat).kind() { let field_count = match cx.typeck_results().pat_ty(pat).kind() {
ty::Tuple(subs) => subs.len(), 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 clippy_utils::{is_refutable, peel_hir_pat_refs, recurse_or_patterns};
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::def::{CtorKind, DefKind, Res}; 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_lint::LateContext;
use rustc_middle::ty::{self, VariantDef}; use rustc_middle::ty::{self, VariantDef};
use rustc_span::sym; 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. // covered by the set of guards that cover it, but that's really hard to do.
recurse_or_patterns(arm.pat, |pat| { recurse_or_patterns(arm.pat, |pat| {
let path = match &peel_hir_pat_refs(pat).0.kind { let path = match &peel_hir_pat_refs(pat).0.kind {
PatKind::Path(path) => { PatKind::Expr(PatExpr {
let id = match cx.qpath_res(path, pat.hir_id) { 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( Res::Def(
DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst, DefKind::Const | DefKind::ConstParam | DefKind::AnonConst | DefKind::InlineConst,
_, _,

View file

@ -8,7 +8,9 @@ use clippy_utils::{
}; };
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionNone; 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_lint::LateContext;
use rustc_span::sym; 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; return !matches!(annot, BindingMode(ByRef::Yes(_), _)) && pat_ident.name == first_seg.ident.name;
}, },
// Example: `Custom::TypeA => Custom::TypeB`, or `None => None` // 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| { return over(p_path.segments, e_path.segments, |p_seg, e_seg| {
p_seg.ident.name == e_seg.ident.name 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_errors::Applicability;
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::def::{DefKind, Res}; 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_lint::LateContext;
use rustc_middle::ty::{self, GenericArgKind, Ty}; use rustc_middle::ty::{self, GenericArgKind, Ty};
use rustc_span::{Span, Symbol, sym}; use rustc_span::{Span, Symbol, sym};
@ -149,8 +149,12 @@ fn find_method_and_type<'tcx>(
None None
} }
}, },
PatKind::Path(ref path) => { PatKind::Expr(PatExpr {
if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(path, check_pat.hir_id) 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 Some(variant_id) = cx.tcx.opt_parent(ctor_id)
{ {
let method = if cx.tcx.lang_items().option_none_variant() == Some(variant_id) { let method = if cx.tcx.lang_items().option_none_variant() == Some(variant_id) {
@ -351,10 +355,20 @@ fn found_good_method<'tcx>(
None None
} }
}, },
(PatKind::TupleStruct(path_left, patterns, _), PatKind::Path(path_right)) (
| (PatKind::Path(path_left), PatKind::TupleStruct(path_right, patterns, _)) PatKind::TupleStruct(path_left, patterns, _),
if patterns.len() == 1 => 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 { if let PatKind::Wild = patterns[0].kind {
find_good_method_for_match( find_good_method_for_match(
cx, cx,
@ -389,7 +403,13 @@ fn found_good_method<'tcx>(
None 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, _ => 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 (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 (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(spe_trait_id) = cx.tcx.lang_items().structural_peq_trait()
&& let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait() && let Some(pe_trait_id) = cx.tcx.lang_items().eq_trait()
@ -331,8 +331,10 @@ impl<'a> PatState<'a> {
#[expect(clippy::similar_names)] #[expect(clippy::similar_names)]
fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool { fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool {
match pat.kind { match pat.kind {
PatKind::Path(_) PatKind::Expr(PatExpr {
if match *cx.typeck.pat_ty(pat).peel_refs().kind() { 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::Adt(adt, _) => adt.is_enum() || (adt.is_struct() && !adt.non_enum_variant().fields.is_empty()),
ty::Tuple(tys) => !tys.is_empty(), ty::Tuple(tys) => !tys.is_empty(),
ty::Array(_, len) => len.try_to_target_usize(cx.tcx) != Some(1), ty::Array(_, len) => len.try_to_target_usize(cx.tcx) != Some(1),
@ -386,7 +388,6 @@ impl<'a> PatState<'a> {
| PatKind::Binding(_, _, _, None) | PatKind::Binding(_, _, _, None)
| PatKind::Expr(_) | PatKind::Expr(_)
| PatKind::Range(..) | PatKind::Range(..)
| PatKind::Path(_)
| PatKind::Never | PatKind::Never
| PatKind::Err(_) => { | PatKind::Err(_) => {
*self = PatState::Wild; *self = PatState::Wild;

View file

@ -7,7 +7,9 @@ use clippy_utils::{
use rustc_errors::Applicability; use rustc_errors::Applicability;
use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
use rustc_hir::def::Res; 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_lint::{LateContext, LateLintPass};
use rustc_session::declare_lint_pass; use rustc_session::declare_lint_pass;
use rustc_span::SyntaxContext; use rustc_span::SyntaxContext;
@ -281,7 +283,11 @@ 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_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], _) => { PatKind::TupleStruct(ref qpath, [first_pat], _) => {
is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr) is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), ResultErr)
&& matches!(first_pat.kind, PatKind::Wild) && 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::intravisit::{InferKind, Visitor, VisitorExt, walk_ty};
use rustc_hir::{ use rustc_hir::{
self as hir, AmbigArg, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, 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_hir_analysis::lower_ty;
use rustc_lint::{LateContext, LateLintPass}; use rustc_lint::{LateContext, LateLintPass};
@ -258,7 +258,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
&& self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS) && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
&& let Some(&StackItem::Check { impl_id, .. }) = self.stack.last() && let Some(&StackItem::Check { impl_id, .. }) = self.stack.last()
// get the path from the pattern // 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::TupleStruct(QPath::Resolved(_, path), _, _)
| PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind | PatKind::Struct(QPath::Resolved(_, path), _, _) = pat.kind
&& cx.typeck_results().pat_ty(pat) == cx.tcx.type_of(impl_id).instantiate_identity() && 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.qpath(qpath);
self.slice(fields, |pat| self.pat(pat)); 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) => { PatKind::Tuple(fields, skip_pos) => {
bind!(self, fields); bind!(self, fields);
kind!("Tuple({fields}, {skip_pos:?})"); kind!("Tuple({fields}, {skip_pos:?})");

View file

@ -524,7 +524,6 @@ impl HirEqInterExpr<'_, '_, '_> {
} }
eq 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::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::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)) => { (&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); self.hash_pat(pat);
} }
}, },
PatKind::Path(ref qpath) => self.hash_qpath(qpath),
PatKind::Range(s, e, i) => { PatKind::Range(s, e, i) => {
if let Some(s) = s { if let Some(s) = s {
self.hash_pat_expr(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, self as hir, Arm, BindingMode, Block, BlockCheckMode, Body, ByRef, Closure, ConstArgKind, ConstContext,
Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind, Destination, Expr, ExprField, ExprKind, FnDecl, FnRetTy, GenericArgs, HirId, Impl, ImplItem, ImplItemKind,
ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, ImplItemRef, Item, ItemKind, LangItem, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat,
PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind, TraitItemRef, TraitRef, PatExpr, PatExprKind, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitItem, TraitItemKind,
TyKind, UnOp, def, TraitItemRef, TraitRef, TyKind, UnOp, def,
}; };
use rustc_lexer::{TokenKind, tokenize}; use rustc_lexer::{TokenKind, tokenize};
use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_lint::{LateContext, Level, Lint, LintContext};
@ -560,7 +560,20 @@ macro_rules! maybe_path {
}; };
} }
maybe_path!(Expr, ExprKind); 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); maybe_path!(Ty, TyKind);
/// If `maybe_path` is a path node, resolves it, otherwise returns `Res::Err` /// 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::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::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)),
PatKind::Box(pat) | PatKind::Ref(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) => { PatKind::Or(pats) => {
// TODO: should be the honest check, that pats is exhaustive set // TODO: should be the honest check, that pats is exhaustive set
are_refutable(cx, pats) are_refutable(cx, pats)

View file

@ -29,6 +29,7 @@ const used_const: isize = 0;
pub const used_const2: isize = used_const; pub const used_const2: isize = used_const;
const USED_CONST: isize = 1; const USED_CONST: isize = 1;
const CONST_USED_IN_ENUM_DISCRIMINANT: isize = 11; const CONST_USED_IN_ENUM_DISCRIMINANT: isize = 11;
const CONST_USED_IN_RANGE_PATTERN: isize = 12;
pub type typ = *const UsedStruct4; pub type typ = *const UsedStruct4;
pub struct PubStruct; pub struct PubStruct;
@ -81,6 +82,7 @@ pub fn pub_fn() {
match i { match i {
USED_STATIC => (), USED_STATIC => (),
USED_CONST => (), USED_CONST => (),
CONST_USED_IN_RANGE_PATTERN..100 => {}
_ => () _ => ()
} }
f::<StructUsedInGeneric>(); f::<StructUsedInGeneric>();

View file

@ -17,19 +17,19 @@ LL | const priv_const: isize = 0;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: struct `PrivStruct` is never constructed error: struct `PrivStruct` is never constructed
--> $DIR/lint-dead-code-1.rs:35:8 --> $DIR/lint-dead-code-1.rs:36:8
| |
LL | struct PrivStruct; LL | struct PrivStruct;
| ^^^^^^^^^^ | ^^^^^^^^^^
error: enum `priv_enum` is never used error: enum `priv_enum` is never used
--> $DIR/lint-dead-code-1.rs:64:6 --> $DIR/lint-dead-code-1.rs:65:6
| |
LL | enum priv_enum { foo2, bar2 } LL | enum priv_enum { foo2, bar2 }
| ^^^^^^^^^ | ^^^^^^^^^
error: variant `bar3` is never constructed error: variant `bar3` is never constructed
--> $DIR/lint-dead-code-1.rs:67:5 --> $DIR/lint-dead-code-1.rs:68:5
| |
LL | enum used_enum { LL | enum used_enum {
| --------- variant in this enum | --------- variant in this enum
@ -38,25 +38,25 @@ LL | bar3
| ^^^^ | ^^^^
error: function `priv_fn` is never used error: function `priv_fn` is never used
--> $DIR/lint-dead-code-1.rs:88:4 --> $DIR/lint-dead-code-1.rs:90:4
| |
LL | fn priv_fn() { LL | fn priv_fn() {
| ^^^^^^^ | ^^^^^^^
error: function `foo` is never used error: function `foo` is never used
--> $DIR/lint-dead-code-1.rs:93:4 --> $DIR/lint-dead-code-1.rs:95:4
| |
LL | fn foo() { LL | fn foo() {
| ^^^ | ^^^
error: function `bar` is never used error: function `bar` is never used
--> $DIR/lint-dead-code-1.rs:98:4 --> $DIR/lint-dead-code-1.rs:100:4
| |
LL | fn bar() { LL | fn bar() {
| ^^^ | ^^^
error: function `baz` is never used error: function `baz` is never used
--> $DIR/lint-dead-code-1.rs:102:4 --> $DIR/lint-dead-code-1.rs:104:4
| |
LL | fn baz() -> impl Copy { LL | fn baz() -> impl Copy {
| ^^^ | ^^^

View file

@ -1,5 +1,7 @@
//@ run-pass //@ run-pass
#![deny(dead_code)]
#[derive(PartialEq, Eq)] #[derive(PartialEq, Eq)]
pub enum Foo { pub enum Foo {
FooA(()), FooA(()),
@ -11,6 +13,7 @@ impl Foo {
const A2: Foo = Self::FooA(()); const A2: Foo = Self::FooA(());
const A3: Self = Foo::FooA(()); const A3: Self = Foo::FooA(());
const A4: Self = Self::FooA(()); const A4: Self = Self::FooA(());
const A5: u32 = 1;
} }
fn main() { fn main() {
@ -35,4 +38,9 @@ fn main() {
Foo::A4 => {}, Foo::A4 => {},
_ => {}, _ => {},
} }
match 3 {
Foo::A5..5 => {}
_ => {}
}
} }

View file

@ -26,16 +26,16 @@ params: [
body: body:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(26) region_scope: Node(28)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).28))
value: value:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0) span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
kind: kind:
Block { Block {
@ -47,7 +47,7 @@ body:
expr: expr:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
kind: kind:
Scope { Scope {
@ -56,14 +56,14 @@ body:
value: value:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0) span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
kind: kind:
Match { Match {
scrutinee: scrutinee:
Expr { Expr {
ty: Foo ty: Foo
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
kind: kind:
Scope { Scope {
@ -72,7 +72,7 @@ body:
value: value:
Expr { Expr {
ty: Foo ty: Foo
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(28)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0) span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
kind: kind:
VarRef { VarRef {
@ -123,16 +123,16 @@ body:
body: body:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(13)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(14)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(14) region_scope: Node(15)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).14)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).15))
value: value:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(13)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(14)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
kind: kind:
Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false) Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false)
@ -140,8 +140,8 @@ body:
} }
} }
} }
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).14))
scope: Node(13) scope: Node(14)
span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0) span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0)
} }
Arm { Arm {
@ -175,16 +175,16 @@ body:
body: body:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(19)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(20)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(20) region_scope: Node(21)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).20)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).21))
value: value:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(19)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(20)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
kind: kind:
Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false) Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false)
@ -192,8 +192,8 @@ body:
} }
} }
} }
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).20))
scope: Node(19) scope: Node(20)
span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0) span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0)
} }
Arm { Arm {
@ -219,16 +219,16 @@ body:
body: body:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
kind: kind:
Scope { Scope {
region_scope: Node(25) region_scope: Node(27)
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).25)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).27))
value: value:
Expr { Expr {
ty: bool ty: bool
temp_lifetime: TempLifetime { temp_lifetime: Some(Node(24)), backwards_incompatible: None } temp_lifetime: TempLifetime { temp_lifetime: Some(Node(26)), backwards_incompatible: None }
span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
kind: kind:
Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false) Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false)
@ -236,8 +236,8 @@ body:
} }
} }
} }
lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24)) lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26))
scope: Node(24) scope: Node(26)
span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0) span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0)
} }
] ]