From f47ad710595c1d87daa8f6b67045574c7304f83e Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 12 Dec 2024 10:37:37 +0000 Subject: [PATCH 1/3] Eliminate PatKind::Path --- compiler/rustc_ast_lowering/src/expr.rs | 6 +- compiler/rustc_ast_lowering/src/pat.rs | 33 +++++++---- compiler/rustc_hir/src/hir.rs | 7 +-- compiler/rustc_hir/src/intravisit.rs | 3 - compiler/rustc_hir/src/pat_util.rs | 5 +- .../rustc_hir_analysis/src/check/region.rs | 1 - .../src/hir_ty_lowering/lint.rs | 4 +- compiler/rustc_hir_pretty/src/lib.rs | 3 - compiler/rustc_hir_typeck/src/expr.rs | 1 - .../rustc_hir_typeck/src/expr_use_visitor.rs | 12 ++-- .../src/fn_ctxt/suggestions.rs | 10 ++-- .../rustc_hir_typeck/src/method/suggest.rs | 3 +- compiler/rustc_hir_typeck/src/pat.rs | 56 +++++++++++-------- compiler/rustc_lint/src/internal.rs | 10 ++-- compiler/rustc_lint/src/nonstandard_style.rs | 8 ++- .../rustc_mir_build/src/thir/pattern/mod.rs | 4 -- compiler/rustc_passes/src/dead.rs | 7 +-- compiler/rustc_passes/src/input_stats.rs | 1 - src/librustdoc/clean/utils.rs | 3 +- src/librustdoc/html/render/span_map.rs | 26 +++++---- .../clippy_lints/src/equatable_if_let.rs | 2 +- .../clippy_lints/src/manual_let_else.rs | 9 ++- .../src/manual_unwrap_or_default.rs | 4 +- .../src/matches/collapsible_match.rs | 8 ++- .../clippy_lints/src/matches/manual_ok_err.rs | 13 ++++- .../src/matches/manual_unwrap_or.rs | 8 ++- .../clippy_lints/src/matches/manual_utils.rs | 10 ++-- .../clippy_lints/src/matches/match_as_ref.rs | 4 +- .../src/matches/match_same_arms.rs | 8 ++- .../src/matches/match_wild_enum.rs | 11 +++- .../src/matches/needless_match.rs | 12 +++- .../src/matches/redundant_pattern_match.rs | 36 +++++++++--- .../clippy_lints/src/matches/single_match.rs | 21 +++---- .../clippy_lints/src/option_if_let_else.rs | 10 +++- src/tools/clippy/clippy_lints/src/use_self.rs | 4 +- .../clippy/clippy_lints/src/utils/author.rs | 5 -- .../clippy/clippy_utils/src/hir_utils.rs | 2 - src/tools/clippy/clippy_utils/src/lib.rs | 25 +++++++-- tests/ui/thir-print/thir-tree-match.stdout | 52 ++++++++--------- 39 files changed, 273 insertions(+), 174 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index b932915dc298..1267281f73eb 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1391,7 +1391,11 @@ fn destructure_assign_mut( None, ); // 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); } } diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 3c78ed0497d7..cde8ddbfe03c 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -69,7 +69,16 @@ fn lower_pat_mut(&mut self, mut pattern: &Pat) -> hir::Pat<'hir> { ImplTraitContext::Disallowed(ImplTraitPosition::Path), 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) => { let qpath = self.lower_qpath( @@ -304,16 +313,20 @@ fn lower_pat_ident( ) } Some(res) => { - let hir_id = self.next_id(); let res = self.lower_res(res); - hir::PatKind::Path(hir::QPath::Resolved( - None, - self.arena.alloc(hir::Path { - span: self.lower_span(ident.span), - res, - segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), hir_id, res)], - }), - )) + let span = self.lower_span(ident.span); + hir::PatKind::Expr(self.arena.alloc(hir::PatExpr { + kind: hir::PatExprKind::Path(hir::QPath::Resolved( + None, + self.arena.alloc(hir::Path { + span, + res, + segments: arena_vec![self; hir::PathSegment::new(self.lower_ident(ident), self.next_id(), res)], + }), + )), + hir_id: self.next_id(), + span, + })) } } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a396d705cbb6..af2f86b67e00 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1437,7 +1437,7 @@ fn walk_short_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) -> bool { use PatKind::*; 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), 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)), @@ -1464,7 +1464,7 @@ fn walk_(&self, it: &mut impl FnMut(&Pat<'hir>) -> bool) { use PatKind::*; 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), 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)), @@ -1618,9 +1618,6 @@ pub enum PatKind<'hir> { /// A never pattern `!`. Never, - /// A path pattern for a unit struct/variant or a (maybe-associated) constant. - Path(QPath<'hir>), - /// A tuple pattern (e.g., `(a, b)`). /// If the `..` pattern fragment is present, then `Option` denotes its position. /// `0 <= position <= subpats.len()` diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index b0d80d0f8092..31764ab12094 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -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)); 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, _) => { try_visit!(visitor.visit_qpath(qpath, pattern.hir_id, pattern.span)); walk_list!(visitor, visit_pat_field, fields); diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs index bb853985c7d8..8dd1e4e82927 100644 --- a/compiler/rustc_hir/src/pat_util.rs +++ b/compiler/rustc_hir/src/pat_util.rs @@ -105,7 +105,10 @@ pub fn necessary_variants(&self) -> Vec { let mut variants = vec![]; self.walk(|p| match &p.kind { 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::Struct(hir::QPath::Resolved(_, path), ..) => { if let Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), id) = diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 83c69dc2ef41..d43c65c0023b 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -703,7 +703,6 @@ fn is_binding_pat(pat: &hir::Pat<'_>) -> bool { | PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..) | PatKind::Wild | PatKind::Never - | PatKind::Path(_) | PatKind::Expr(_) | PatKind::Range(_, _, _) | PatKind::Err(_) => false, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 539c5f6a20af..44f7a035a10f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -41,8 +41,8 @@ pub(super) fn prohibit_or_lint_bare_trait_object_ty( kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)), .. }) - | hir::Node::Pat(hir::Pat { - kind: hir::PatKind::Path(hir::QPath::TypeRelative(qself, _)), + | hir::Node::PatExpr(hir::PatExpr { + kind: hir::PatExprKind::Path(hir::QPath::TypeRelative(qself, _)), .. }) if qself.hir_id == self_ty.hir_id => true, _ => false, diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index afc0f627f696..a91afa51230d 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -1906,9 +1906,6 @@ fn print_pat(&mut self, pat: &hir::Pat<'_>) { } self.pclose(); } - PatKind::Path(ref qpath) => { - self.print_qpath(qpath, true); - } PatKind::Struct(ref qpath, fields, etc) => { self.print_qpath(qpath, true); self.nbsp(); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 1c828591bcbd..f79667e59bae 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -480,7 +480,6 @@ pub(super) fn pat_guaranteed_to_constitute_read_for_never(&self, pat: &hir::Pat< hir::PatKind::Binding(_, _, _, _) | hir::PatKind::Struct(_, _, _) | hir::PatKind::TupleStruct(_, _, _) - | hir::PatKind::Path(_) | hir::PatKind::Tuple(_, _) | hir::PatKind::Box(_) | hir::PatKind::Ref(_, _) diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index 1f48b703e4ac..d37c68f82fb2 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -11,10 +11,9 @@ use hir::pat_util::EnumerateAndAdjustIterator as _; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; -use rustc_hir as hir; use rustc_hir::def::{CtorOf, Res}; 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_middle::hir::place::ProjectionKind; // Export these here so that Clippy can use them. @@ -564,11 +563,11 @@ fn maybe_read_scrutinee<'t>( // FIXME(never_patterns): does this do what I expect? 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 // 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 { Res::Def(DefKind::Const, _) | Res::Def(DefKind::AssocConst, _) => { // Named constants have to be equated with the value @@ -581,7 +580,7 @@ fn maybe_read_scrutinee<'t>( // Otherwise, this is a struct/enum variant, and so it's // only a read if we need to read the discriminant. 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 @@ fn cat_pattern( } } - PatKind::Path(_) - | PatKind::Binding(.., None) + PatKind::Binding(.., None) | PatKind::Expr(..) | PatKind::Range(..) | PatKind::Never diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 928010c03c2e..aea2e0fd3a30 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -5,12 +5,12 @@ use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::packed::Pu128; use rustc_errors::{Applicability, Diag, MultiSpan}; -use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::lang_items::LangItem; use rustc_hir::{ - Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, - Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicateKind, expr_needs_parens, + self as hir, Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, + 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::hir_ty_lowering::HirTyLowerer; @@ -1422,8 +1422,8 @@ pub(crate) fn suggest_option_to_bool( // since the user probably just misunderstood how `let else` // and `&&` work together. if let Some((_, hir::Node::LetStmt(local))) = cond_parent - && let hir::PatKind::Path(qpath) | hir::PatKind::TupleStruct(qpath, _, _) = - &local.pat.kind + && let hir::PatKind::Expr(PatExpr { kind: PatExprKind::Path(qpath), .. }) + | hir::PatKind::TupleStruct(qpath, _, _) = &local.pat.kind && let hir::QPath::Resolved(None, path) = qpath && let Some(did) = path .res diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 5d4e67d1a0e6..e4a6a0fedc5a 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -177,8 +177,7 @@ pub(crate) fn report_method_error( }) | hir::Node::Pat(&hir::Pat { 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), ..), span, .. diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index cbd1db2ca255..0aa2f1110fb3 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -11,8 +11,8 @@ use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::pat_util::EnumerateAndAdjustIterator; use rustc_hir::{ - self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatKind, - expr_needs_parens, + self as hir, BindingMode, ByRef, ExprKind, HirId, LangItem, Mutability, Pat, PatExpr, + PatExprKind, PatKind, expr_needs_parens, }; use rustc_infer::infer; use rustc_middle::traits::PatternOriginExpr; @@ -312,9 +312,9 @@ pub(crate) fn check_pat_top( 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 path_res = match &pat.kind { - PatKind::Path(qpath) => { - Some(self.resolve_ty_and_res_fully_qualified_call(qpath, pat.hir_id, pat.span)) + let path_res = match pat.kind { + PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref qpath), hir_id, span }) => { + Some(self.resolve_ty_and_res_fully_qualified_call(qpath, *hir_id, *span)) } _ => None, }; @@ -333,6 +333,19 @@ fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo< PatKind::Wild | PatKind::Err(_) => expected, // We allow any type here; we ensure that the type is uninhabited during match checking. 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::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti), PatKind::Binding(ba, var_id, ident, sub) => { @@ -341,9 +354,6 @@ fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo< PatKind::TupleStruct(ref qpath, subpats, ddpos) => { 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) => { self.check_pat_struct(pat, qpath, fields, has_rest_pat, expected, pat_info) } @@ -456,16 +466,7 @@ fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option) -> A | PatKind::Slice(..) => AdjustMode::Peel, // A never pattern behaves somewhat like a literal or unit variant. PatKind::Never => 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, - }, - PatKind::Path(_) => match opt_path_res.unwrap() { + PatKind::Expr(PatExpr { kind: PatExprKind::Path(_), .. }) => match opt_path_res.unwrap() { // 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. // Although it would be possible to *also* peel the types of the constants too. @@ -476,6 +477,17 @@ fn calc_adjust_mode(&self, pat: &'tcx Pat<'tcx>, opt_path_res: Option) -> A // a reference type wherefore peeling doesn't give up any expressiveness. _ => 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`. PatKind::Ref(..) => AdjustMode::Pass, // A `_` pattern works with any expected type, so there's no need to do anything. @@ -1001,7 +1013,6 @@ fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) { PatKind::Wild | PatKind::Never | PatKind::Binding(..) - | PatKind::Path(..) | PatKind::Box(..) | PatKind::Deref(_) | PatKind::Ref(..) @@ -1139,7 +1150,8 @@ fn check_pat_struct( fn check_pat_path( &self, - hir_id: HirId, + path_id: HirId, + pat_id_for_diag: HirId, span: Span, qpath: &hir::QPath<'_>, path_resolution: (Res, Option>, &'tcx [hir::PathSegment<'tcx>]), @@ -1193,11 +1205,11 @@ fn check_pat_path( // Type-check the path. 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) = 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 } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 166ff60f7e1e..546df4497adf 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -6,7 +6,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{ 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_session::{declare_lint_pass, declare_tool_lint}; @@ -164,11 +164,9 @@ fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx Ty<'tcx, AmbigArg>) { TyKind::Path(QPath::Resolved(_, path)) => { if lint_ty_kind_usage(cx, &path.res) { let span = match cx.tcx.parent_hir_node(ty.hir_id) { - Node::Pat(Pat { - kind: - PatKind::Path(qpath) - | PatKind::TupleStruct(qpath, ..) - | PatKind::Struct(qpath, ..), + Node::PatExpr(PatExpr { kind: PatExprKind::Path(qpath), .. }) + | Node::Pat(Pat { + kind: PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..), .. }) | Node::Expr( diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index e09049f322fa..0c180ab95706 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,7 +1,7 @@ use rustc_abi::ExternAbi; use rustc_hir::def::{DefKind, Res}; 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_session::config::CrateType; use rustc_session::{declare_lint, declare_lint_pass}; @@ -527,7 +527,11 @@ fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) { fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) { // 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 [segment] = path.segments { NonUpperCaseGlobals::check_upper_case( diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 44b038bb5faf..20a728d6d5b2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -332,10 +332,6 @@ fn lower_pattern_unadjusted(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box { - return self.lower_path(qpath, pat.hir_id, pat.span); - } - hir::PatKind::Deref(subpattern) => { let mutable = self.typeck_results.pat_has_ref_mut_binding(subpattern); let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not }; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index e5b63b9b4a60..bc2bebdfef68 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -10,11 +10,10 @@ use rustc_abi::FieldIdx; use rustc_data_structures::unord::UnordSet; use rustc_errors::MultiSpan; -use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{Node, PatKind, TyKind}; +use rustc_hir::{self as hir, Node, PatExpr, PatExprKind, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; @@ -637,8 +636,8 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { let res = self.typeck_results().qpath_res(path, pat.hir_id); self.handle_field_pattern_match(pat, res, fields); } - PatKind::Path(ref qpath) => { - let res = self.typeck_results().qpath_res(qpath, pat.hir_id); + PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref qpath), hir_id, .. }) => { + let res = self.typeck_results().qpath_res(qpath, *hir_id); self.handle_res(res); } PatKind::TupleStruct(ref qpath, fields, dotdot) => { diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 8b10543f6fdb..75b62a40ff9f 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -298,7 +298,6 @@ fn visit_pat(&mut self, p: &'v hir::Pat<'v>) { TupleStruct, Or, Never, - Path, Tuple, Box, Deref, diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 80dc6b7250cc..77040aeb94d7 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -303,7 +303,8 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { return kw::Underscore; } 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) => { pats.iter().map(|p| name_from_pat(p).to_string()).collect::>().join(" | ") } diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs index 85f87f01afdf..a15ac155123d 100644 --- a/src/librustdoc/html/render/span_map.rs +++ b/src/librustdoc/html/render/span_map.rs @@ -4,7 +4,9 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; 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::ty::TyCtxt; use rustc_span::hygiene::MacroKind; @@ -191,17 +193,21 @@ fn infer_id(&mut self, hir_id: HirId, expr_hir_id: Option, span: Span) { } fn handle_pat(&mut self, p: &Pat<'_>) { + let mut check_qpath = |qpath, hir_id| match qpath { + QPath::TypeRelative(_, path) if matches!(path.res, Res::Err) => { + self.infer_id(path.hir_id, Some(hir_id), qpath.span()); + } + QPath::Resolved(_, path) => self.handle_path(path), + _ => {} + }; match p.kind { 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) => { - self.infer_id(path.hir_id, Some(p.hir_id), qpath.span()); - } - QPath::Resolved(_, path) => self.handle_path(path), - _ => {} - }, + 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) => { for pat in pats { self.handle_pat(pat); diff --git a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs index 8a5cf7f56d5f..7ca2c9536998 100644 --- a/src/tools/clippy/clippy_lints/src/equatable_if_let.rs +++ b/src/tools/clippy/clippy_lints/src/equatable_if_let.rs @@ -56,7 +56,7 @@ fn array_rec(pats: &[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, } } diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index 8503dde3fb6b..274785061b3f 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -7,7 +7,7 @@ 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; } diff --git a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs index 8f8390b6f3f9..7b95399c907c 100644 --- a/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs +++ b/src/tools/clippy/clippy_lints/src/manual_unwrap_or_default.rs @@ -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 { } 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. diff --git a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs index 99a7b8c74be8..97e8423695d9 100644 --- a/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/collapsible_match.rs @@ -8,7 +8,7 @@ }; 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, } } diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs b/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs index b1a555b91d1b..3deaaf96c1e8 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_ok_err.rs @@ -6,7 +6,7 @@ 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 }, diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs index 59d375200117..b69294d567d1 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs @@ -7,7 +7,7 @@ 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) diff --git a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs index 0b57740064c1..2ad55d9bf1fd 100644 --- a/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs +++ b/src/tools/clippy/clippy_lints/src/matches/manual_utils.rs @@ -11,7 +11,7 @@ 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 @@ fn f<'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 => { diff --git a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs index 6c123649afc2..b1889d26c932 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_as_ref.rs @@ -2,7 +2,7 @@ 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) ) } diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 28e05c273d5c..41e4c75f843e 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -7,7 +7,7 @@ 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 @@ fn from_pat(cx: &LateContext<'_>, arena: &'a DroplessArena, pat: &'a Pat<'_>) -> 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(), diff --git a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs index 595655600890..11b588b33554 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_wild_enum.rs @@ -3,7 +3,7 @@ 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, _, diff --git a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs index 0d5575efc220..7e65d586110e 100644 --- a/src/tools/clippy/clippy_lints/src/matches/needless_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/needless_match.rs @@ -8,7 +8,9 @@ }; 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 }); diff --git a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs index edac97344a03..393399660131 100644 --- a/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/redundant_pattern_match.rs @@ -9,7 +9,7 @@ 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, } } diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 38f876fed802..2f46eaaabb36 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -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 @@ fn add_struct_pats<'tcx>( #[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 @@ fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool { | PatKind::Binding(_, _, _, None) | PatKind::Expr(_) | PatKind::Range(..) - | PatKind::Path(_) | PatKind::Never | PatKind::Err(_) => { *self = PatState::Wild; diff --git a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs index 6d9e75f51d66..de9f055863cb 100644 --- a/src/tools/clippy/clippy_lints/src/option_if_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/option_if_let_else.rs @@ -7,7 +7,9 @@ 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) diff --git a/src/tools/clippy/clippy_lints/src/use_self.rs b/src/tools/clippy/clippy_lints/src/use_self.rs index 84b6430294f3..47ce2243aa09 100644 --- a/src/tools/clippy/clippy_lints/src/use_self.rs +++ b/src/tools/clippy/clippy_lints/src/use_self.rs @@ -10,7 +10,7 @@ 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 @@ fn check_pat(&mut self, cx: &LateContext<'_>, pat: &Pat<'_>) { && 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() diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 4dcc8ac7fb0a..6bad78cf8718 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -708,11 +708,6 @@ macro_rules! kind { 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:?})"); diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index d76231a6eeaa..d0eb5318e645 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -524,7 +524,6 @@ fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool { } 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 @@ pub fn hash_pat(&mut self, pat: &Pat<'_>) { 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); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index e471dfb6ef19..5a5227af9074 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -106,8 +106,8 @@ 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 @@ fn qpath_opt(&self) -> Option<&QPath<'hir>> { }; } 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 @@ fn are_refutable<'a, I: IntoIterator>>(cx: &LateContext<'_>, 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) diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout index 916f296ccfc6..910582ae4d9e 100644 --- a/tests/ui/thir-print/thir-tree-match.stdout +++ b/tests/ui/thir-print/thir-tree-match.stdout @@ -26,16 +26,16 @@ params: [ body: Expr { 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) kind: Scope { - region_scope: Node(26) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26)) + region_scope: Node(28) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).28)) value: Expr { 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) kind: Block { @@ -47,7 +47,7 @@ body: expr: Expr { 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) kind: Scope { @@ -56,14 +56,14 @@ body: value: Expr { 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) kind: Match { scrutinee: Expr { 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) kind: Scope { @@ -72,7 +72,7 @@ body: value: Expr { 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) kind: VarRef { @@ -123,16 +123,16 @@ body: body: Expr { 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) kind: Scope { - region_scope: Node(14) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).14)) + region_scope: Node(15) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).15)) value: Expr { 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) kind: 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)) - scope: Node(13) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).14)) + scope: Node(14) span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0) } Arm { @@ -175,16 +175,16 @@ body: body: Expr { 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) kind: Scope { - region_scope: Node(20) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).20)) + region_scope: Node(21) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).21)) value: Expr { 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) kind: 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)) - scope: Node(19) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).20)) + scope: Node(20) span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0) } Arm { @@ -219,16 +219,16 @@ body: body: Expr { 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) kind: Scope { - region_scope: Node(25) - lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).25)) + region_scope: Node(27) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).27)) value: Expr { 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) kind: 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)) - scope: Node(24) + lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26)) + scope: Node(26) span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0) } ] From 8f09abb49757a65f143c6794fcb22a70945e67d1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Jan 2025 08:38:56 +0000 Subject: [PATCH 2/3] Add regression test showing we don't realize some consts are used --- tests/ui/lint/dead-code/lint-dead-code-1.rs | 2 ++ tests/ui/lint/dead-code/lint-dead-code-1.stderr | 14 +++++++------- tests/ui/pattern/issue-110508.rs | 8 +++++++- tests/ui/pattern/issue-110508.stderr | 17 +++++++++++++++++ 4 files changed, 33 insertions(+), 8 deletions(-) create mode 100644 tests/ui/pattern/issue-110508.stderr diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.rs b/tests/ui/lint/dead-code/lint-dead-code-1.rs index ddcafedf7bc5..a7f654b5d8bf 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-1.rs +++ b/tests/ui/lint/dead-code/lint-dead-code-1.rs @@ -29,6 +29,7 @@ mod foo2 { pub const used_const2: isize = used_const; const USED_CONST: isize = 1; const CONST_USED_IN_ENUM_DISCRIMINANT: isize = 11; +const CONST_USED_IN_RANGE_PATTERN: isize = 12; pub type typ = *const UsedStruct4; pub struct PubStruct; @@ -81,6 +82,7 @@ pub fn pub_fn() { match i { USED_STATIC => (), USED_CONST => (), + CONST_USED_IN_RANGE_PATTERN..100 => {} _ => () } f::(); diff --git a/tests/ui/lint/dead-code/lint-dead-code-1.stderr b/tests/ui/lint/dead-code/lint-dead-code-1.stderr index eb728b5b9305..c4410114cea8 100644 --- a/tests/ui/lint/dead-code/lint-dead-code-1.stderr +++ b/tests/ui/lint/dead-code/lint-dead-code-1.stderr @@ -17,19 +17,19 @@ LL | const priv_const: isize = 0; | ^^^^^^^^^^ 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; | ^^^^^^^^^^ 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 } | ^^^^^^^^^ 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 { | --------- variant in this enum @@ -38,25 +38,25 @@ LL | bar3 | ^^^^ 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() { | ^^^^^^^ 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() { | ^^^ 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() { | ^^^ 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 { | ^^^ diff --git a/tests/ui/pattern/issue-110508.rs b/tests/ui/pattern/issue-110508.rs index 6ed0476183ec..980d8d52f1d5 100644 --- a/tests/ui/pattern/issue-110508.rs +++ b/tests/ui/pattern/issue-110508.rs @@ -1,4 +1,4 @@ -//@ run-pass +#![deny(dead_code)] #[derive(PartialEq, Eq)] pub enum Foo { @@ -11,6 +11,7 @@ impl Foo { const A2: Foo = Self::FooA(()); const A3: Self = Foo::FooA(()); const A4: Self = Self::FooA(()); + const A5: u32 = 1; //~ ERROR: dead_code } fn main() { @@ -35,4 +36,9 @@ fn main() { Foo::A4 => {}, _ => {}, } + + match 3 { + Foo::A5..5 => {} + _ => {} + } } diff --git a/tests/ui/pattern/issue-110508.stderr b/tests/ui/pattern/issue-110508.stderr new file mode 100644 index 000000000000..aaec91167692 --- /dev/null +++ b/tests/ui/pattern/issue-110508.stderr @@ -0,0 +1,17 @@ +error: associated constant `A5` is never used + --> $DIR/issue-110508.rs:14:11 + | +LL | impl Foo { + | -------- associated constant in this implementation +... +LL | const A5: u32 = 1; + | ^^ + | +note: the lint level is defined here + --> $DIR/issue-110508.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to 1 previous error + From 559648a0a4c942993c321d999f708e64f169b245 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 29 Jan 2025 08:52:43 +0000 Subject: [PATCH 3/3] Handle all `PatExpr`s in dead code analysis --- compiler/rustc_passes/src/dead.rs | 17 ++++++++++++----- tests/ui/pattern/issue-110508.rs | 4 +++- tests/ui/pattern/issue-110508.stderr | 17 ----------------- 3 files changed, 15 insertions(+), 23 deletions(-) delete mode 100644 tests/ui/pattern/issue-110508.stderr diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index bc2bebdfef68..95f18eaa7ef1 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -13,7 +13,7 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, Node, PatExpr, PatExprKind, PatKind, TyKind}; +use rustc_hir::{self as hir, Node, PatKind, TyKind}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::privacy::Level; use rustc_middle::query::Providers; @@ -636,10 +636,6 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { let res = self.typeck_results().qpath_res(path, pat.hir_id); self.handle_field_pattern_match(pat, res, fields); } - PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref qpath), hir_id, .. }) => { - let res = self.typeck_results().qpath_res(qpath, *hir_id); - self.handle_res(res); - } PatKind::TupleStruct(ref qpath, fields, dotdot) => { let res = self.typeck_results().qpath_res(qpath, pat.hir_id); self.handle_tuple_field_pattern_match(pat, res, fields, dotdot); @@ -651,6 +647,17 @@ fn visit_pat(&mut self, pat: &'tcx hir::Pat<'tcx>) { 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) { self.handle_res(path.res); intravisit::walk_path(self, path); diff --git a/tests/ui/pattern/issue-110508.rs b/tests/ui/pattern/issue-110508.rs index 980d8d52f1d5..74a8d673e837 100644 --- a/tests/ui/pattern/issue-110508.rs +++ b/tests/ui/pattern/issue-110508.rs @@ -1,3 +1,5 @@ +//@ run-pass + #![deny(dead_code)] #[derive(PartialEq, Eq)] @@ -11,7 +13,7 @@ impl Foo { const A2: Foo = Self::FooA(()); const A3: Self = Foo::FooA(()); const A4: Self = Self::FooA(()); - const A5: u32 = 1; //~ ERROR: dead_code + const A5: u32 = 1; } fn main() { diff --git a/tests/ui/pattern/issue-110508.stderr b/tests/ui/pattern/issue-110508.stderr deleted file mode 100644 index aaec91167692..000000000000 --- a/tests/ui/pattern/issue-110508.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error: associated constant `A5` is never used - --> $DIR/issue-110508.rs:14:11 - | -LL | impl Foo { - | -------- associated constant in this implementation -... -LL | const A5: u32 = 1; - | ^^ - | -note: the lint level is defined here - --> $DIR/issue-110508.rs:1:9 - | -LL | #![deny(dead_code)] - | ^^^^^^^^^ - -error: aborting due to 1 previous error -