From 643fdbd216cfdf6cefc2fef4808c428b81072c37 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github333195615777966@oli-obk.de>
Date: Wed, 11 Dec 2024 20:23:52 +0000
Subject: [PATCH 1/5] Avoid passing a full Expr when only the Span is used

---
 compiler/rustc_hir_typeck/src/expr.rs           | 2 +-
 compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs  | 4 ++--
 compiler/rustc_hir_typeck/src/method/confirm.rs | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 30f02b80ea626..c34739de967bf 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -822,7 +822,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // We always require that the type provided as the value for
         // a type parameter outlives the moment of instantiation.
         let args = self.typeck_results.borrow().node_args(expr.hir_id);
-        self.add_wf_bounds(args, expr);
+        self.add_wf_bounds(args, expr.span);
 
         ty
     }
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 863be3bdcb290..a6276a2e94b6b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -555,11 +555,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Registers obligations that all `args` are well-formed.
-    pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, expr: &hir::Expr<'_>) {
+    pub(crate) fn add_wf_bounds(&self, args: GenericArgsRef<'tcx>, span: Span) {
         for arg in args.iter().filter(|arg| {
             matches!(arg.unpack(), GenericArgKind::Type(..) | GenericArgKind::Const(..))
         }) {
-            self.register_wf_obligation(arg, expr.span, ObligationCauseCode::WellFormed(None));
+            self.register_wf_obligation(arg, span, ObligationCauseCode::WellFormed(None));
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index b31ee1a55d63b..0364de360881e 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -613,7 +613,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
 
         // this is a projection from a trait reference, so we have to
         // make sure that the trait reference inputs are well-formed.
-        self.add_wf_bounds(all_args, self.call_expr);
+        self.add_wf_bounds(all_args, self.call_expr.span);
 
         // the function type must also be well-formed (this is not
         // implied by the args being well-formed because of inherent

From 637ded1c6478da87b91d5aeb04cba919ae8de418 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github333195615777966@oli-obk.de>
Date: Wed, 11 Dec 2024 20:39:50 +0000
Subject: [PATCH 2/5] Avoid passing a full Pat when only the Span/HirId is used

---
 compiler/rustc_hir_typeck/src/pat.rs | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 2a8ed26aa2bee..aa853d5e15457 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 self.check_pat_tuple_struct(pat, qpath, subpats, ddpos, expected, pat_info)
             }
             PatKind::Path(ref qpath) => {
-                self.check_pat_path(pat, qpath, path_res.unwrap(), expected, ti)
+                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)
@@ -1020,7 +1020,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     fn check_pat_path(
         &self,
-        pat: &Pat<'tcx>,
+        hir_id: HirId,
+        span: Span,
         qpath: &hir::QPath<'_>,
         path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
         expected: Ty<'tcx>,
@@ -1039,8 +1040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
             Res::Def(DefKind::AssocFn | DefKind::Ctor(_, CtorKind::Fn) | DefKind::Variant, _) => {
                 let expected = "unit struct, unit variant or constant";
-                let e =
-                    report_unexpected_variant_res(tcx, res, None, qpath, pat.span, E0533, expected);
+                let e = report_unexpected_variant_res(tcx, res, None, qpath, span, E0533, expected);
                 return Ty::new_error(tcx, e);
             }
             Res::SelfCtor(def_id) => {
@@ -1055,7 +1055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         res,
                         None,
                         qpath,
-                        pat.span,
+                        span,
                         E0533,
                         "unit struct",
                     );
@@ -1074,11 +1074,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Type-check the path.
         let (pat_ty, pat_res) =
-            self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id);
+            self.instantiate_value_path(segments, opt_ty, res, span, span, hir_id);
         if let Err(err) =
-            self.demand_suptype_with_origin(&self.pattern_cause(ti, pat.span), expected, pat_ty)
+            self.demand_suptype_with_origin(&self.pattern_cause(ti, span), expected, pat_ty)
         {
-            self.emit_bad_pat_path(err, pat, res, pat_res, pat_ty, segments);
+            self.emit_bad_pat_path(err, hir_id, span, res, pat_res, pat_ty, segments);
         }
         pat_ty
     }
@@ -1121,13 +1121,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn emit_bad_pat_path(
         &self,
         mut e: Diag<'_>,
-        pat: &hir::Pat<'tcx>,
+        hir_id: HirId,
+        pat_span: Span,
         res: Res,
         pat_res: Res,
         pat_ty: Ty<'tcx>,
         segments: &'tcx [hir::PathSegment<'tcx>],
     ) {
-        let pat_span = pat.span;
         if let Some(span) = self.tcx.hir().res_span(pat_res) {
             e.span_label(span, format!("{} defined here", res.descr()));
             if let [hir::PathSegment { ident, .. }] = &*segments {
@@ -1140,7 +1140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         res.descr(),
                     ),
                 );
-                match self.tcx.parent_hir_node(pat.hir_id) {
+                match self.tcx.parent_hir_node(hir_id) {
                     hir::Node::PatField(..) => {
                         e.span_suggestion_verbose(
                             ident.span.shrink_to_hi(),

From 20f5e3f77cc87828c01b915281368851a31a3d5d Mon Sep 17 00:00:00 2001
From: Oli Scherer <github333195615777966@oli-obk.de>
Date: Wed, 11 Dec 2024 16:50:45 +0000
Subject: [PATCH 3/5] Exhaustively handle expressions in patterns

---
 compiler/rustc_ast_lowering/src/expr.rs       | 51 ++++++++--------
 compiler/rustc_ast_lowering/src/index.rs      |  8 +++
 compiler/rustc_ast_lowering/src/lib.rs        |  1 +
 compiler/rustc_ast_lowering/src/pat.rs        | 51 ++++++++++++----
 compiler/rustc_hir/src/hir.rs                 | 29 ++++++++-
 compiler/rustc_hir/src/intravisit.rs          | 18 +++++-
 .../src/hir_ty_lowering/mod.rs                | 42 +++++++------
 compiler/rustc_hir_pretty/src/lib.rs          | 20 ++++++-
 compiler/rustc_hir_typeck/src/expr.rs         |  3 +-
 .../rustc_hir_typeck/src/fn_ctxt/_impl.rs     |  9 +++
 .../rustc_hir_typeck/src/method/suggest.rs    |  5 ++
 compiler/rustc_hir_typeck/src/pat.rs          | 43 ++++++++++----
 compiler/rustc_hir_typeck/src/upvar.rs        |  9 +--
 compiler/rustc_hir_typeck/src/writeback.rs    | 22 +++++--
 compiler/rustc_middle/src/hir/map/mod.rs      |  2 +
 .../rustc_mir_build/src/thir/pattern/mod.rs   | 37 ++++--------
 .../src/default_numeric_fallback.rs           | 16 ++++-
 src/tools/clippy/clippy_lints/src/len_zero.rs | 10 +++-
 .../clippy_lints/src/manual_is_ascii_check.rs | 37 ++++++++----
 .../clippy_lints/src/manual_range_patterns.rs | 13 ++--
 .../clippy_lints/src/matches/match_bool.rs    |  4 +-
 .../src/matches/match_same_arms.rs            |  8 +--
 .../src/matches/match_str_case_mismatch.rs    |  6 +-
 .../src/matches/needless_match.rs             |  4 +-
 .../src/matches/overlapping_arms.rs           |  6 +-
 .../src/matches/redundant_pattern_match.rs    |  4 +-
 .../clippy_lints/src/matches/single_match.rs  |  6 +-
 .../clippy_lints/src/string_patterns.rs       |  4 +-
 .../clippy/clippy_lints/src/utils/author.rs   | 29 +++++++--
 src/tools/clippy/clippy_utils/src/consts.rs   | 59 ++++++++++++-------
 .../clippy/clippy_utils/src/hir_utils.rs      | 35 ++++++++---
 src/tools/clippy/tests/ui/author/if.stdout    |  2 +-
 src/tools/clippy/tests/ui/author/loop.stdout  |  2 +-
 .../clippy/tests/ui/author/matches.stdout     |  4 +-
 .../clippy/tests/ui/author/struct.stdout      |  4 +-
 tests/ui/unpretty/unpretty-expr-fn-arg.stdout |  2 +-
 36 files changed, 412 insertions(+), 193 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 2ad0ff3200e74..fe8ccca072bfb 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -103,17 +103,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
             let kind = match &e.kind {
                 ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
-                ExprKind::ConstBlock(c) => {
-                    let c = self.with_new_scopes(c.value.span, |this| {
-                        let def_id = this.local_def_id(c.id);
-                        hir::ConstBlock {
-                            def_id,
-                            hir_id: this.lower_node_id(c.id),
-                            body: this.lower_const_body(c.value.span, Some(&c.value)),
-                        }
-                    });
-                    hir::ExprKind::ConstBlock(c)
-                }
+                ExprKind::ConstBlock(c) => hir::ExprKind::ConstBlock(self.lower_const_block(c)),
                 ExprKind::Repeat(expr, count) => {
                     let expr = self.lower_expr(expr);
                     let count = self.lower_array_length_to_const_arg(count);
@@ -154,18 +144,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     let ohs = self.lower_expr(ohs);
                     hir::ExprKind::Unary(op, ohs)
                 }
-                ExprKind::Lit(token_lit) => {
-                    let lit_kind = match LitKind::from_token_lit(*token_lit) {
-                        Ok(lit_kind) => lit_kind,
-                        Err(err) => {
-                            let guar =
-                                report_lit_error(&self.tcx.sess.psess, err, *token_lit, e.span);
-                            LitKind::Err(guar)
-                        }
-                    };
-                    let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind));
-                    hir::ExprKind::Lit(lit)
-                }
+                ExprKind::Lit(token_lit) => hir::ExprKind::Lit(self.lower_lit(token_lit, e.span)),
                 ExprKind::IncludedBytes(bytes) => {
                     let lit = self.arena.alloc(respan(
                         self.lower_span(e.span),
@@ -396,6 +375,32 @@ impl<'hir> LoweringContext<'_, 'hir> {
         })
     }
 
+    pub(crate) fn lower_const_block(&mut self, c: &AnonConst) -> hir::ConstBlock {
+        self.with_new_scopes(c.value.span, |this| {
+            let def_id = this.local_def_id(c.id);
+            hir::ConstBlock {
+                def_id,
+                hir_id: this.lower_node_id(c.id),
+                body: this.lower_const_body(c.value.span, Some(&c.value)),
+            }
+        })
+    }
+
+    pub(crate) fn lower_lit(
+        &mut self,
+        token_lit: &token::Lit,
+        span: Span,
+    ) -> &'hir Spanned<LitKind> {
+        let lit_kind = match LitKind::from_token_lit(*token_lit) {
+            Ok(lit_kind) => lit_kind,
+            Err(err) => {
+                let guar = report_lit_error(&self.tcx.sess.psess, err, *token_lit, span);
+                LitKind::Err(guar)
+            }
+        };
+        self.arena.alloc(respan(self.lower_span(span), lit_kind))
+    }
+
     fn lower_unop(&mut self, u: UnOp) -> hir::UnOp {
         match u {
             UnOp::Deref => hir::UnOp::Deref,
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index c3ff7b4b89722..c92f149d24cae 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -209,6 +209,14 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
+    fn visit_pat_lit(&mut self, lit: &'hir PatLit<'hir>) {
+        self.insert(lit.span, lit.hir_id, Node::PatLit(lit));
+
+        self.with_parent(lit.hir_id, |this| {
+            intravisit::walk_pat_lit(this, lit);
+        });
+    }
+
     fn visit_pat_field(&mut self, field: &'hir PatField<'hir>) {
         self.insert(field.span, field.hir_id, Node::PatField(field));
         self.with_parent(field.hir_id, |this| {
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index bac3f974ccae9..8784d729c7cb4 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -35,6 +35,7 @@
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
+#![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
 #![warn(unreachable_pub)]
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index c4bae084a3f8c..25702e3c835cf 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -1,10 +1,13 @@
+use std::sync::Arc;
+
 use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
+use rustc_middle::span_bug;
 use rustc_span::Span;
-use rustc_span::source_map::Spanned;
+use rustc_span::source_map::{Spanned, respan};
 use rustc_span::symbol::Ident;
 
 use super::errors::{
@@ -360,24 +363,46 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     // }
     // m!(S);
     // ```
-    fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::Expr<'hir> {
-        match &expr.kind {
-            ExprKind::Lit(..)
-            | ExprKind::ConstBlock(..)
-            | ExprKind::IncludedBytes(..)
-            | ExprKind::Err(_)
-            | ExprKind::Dummy => {}
-            ExprKind::Path(..) if allow_paths => {}
-            ExprKind::Unary(UnOp::Neg, inner) if matches!(inner.kind, ExprKind::Lit(_)) => {}
+    fn lower_expr_within_pat(&mut self, expr: &Expr, allow_paths: bool) -> &'hir hir::PatLit<'hir> {
+        let err = |guar| hir::PatLitKind::Lit {
+            lit: self.arena.alloc(respan(self.lower_span(expr.span), LitKind::Err(guar))),
+            negated: false,
+        };
+        let kind = match &expr.kind {
+            ExprKind::Lit(lit) => {
+                hir::PatLitKind::Lit { lit: self.lower_lit(lit, expr.span), negated: false }
+            }
+            ExprKind::ConstBlock(c) => hir::PatLitKind::ConstBlock(self.lower_const_block(c)),
+            ExprKind::IncludedBytes(bytes) => hir::PatLitKind::Lit {
+                lit: self.arena.alloc(respan(
+                    self.lower_span(expr.span),
+                    LitKind::ByteStr(Arc::clone(bytes), StrStyle::Cooked),
+                )),
+                negated: false,
+            },
+            ExprKind::Err(guar) => err(*guar),
+            ExprKind::Dummy => span_bug!(expr.span, "lowered ExprKind::Dummy"),
+            ExprKind::Path(qself, path) if allow_paths => hir::PatLitKind::Path(self.lower_qpath(
+                expr.id,
+                qself,
+                path,
+                ParamMode::Optional,
+                AllowReturnTypeNotation::No,
+                ImplTraitContext::Disallowed(ImplTraitPosition::Path),
+                None,
+            )),
+            ExprKind::Unary(UnOp::Neg, inner) if let ExprKind::Lit(lit) = &inner.kind => {
+                hir::PatLitKind::Lit { lit: self.lower_lit(lit, expr.span), negated: true }
+            }
             _ => {
                 let pattern_from_macro = expr.is_approximately_pattern();
                 let guar = self.dcx().emit_err(ArbitraryExpressionInPattern {
                     span: expr.span,
                     pattern_from_macro_note: pattern_from_macro,
                 });
-                return self.arena.alloc(self.expr_err(expr.span, guar));
+                err(guar)
             }
-        }
-        self.lower_expr(expr)
+        };
+        self.arena.alloc(hir::PatLit { hir_id: self.lower_node_id(expr.id), span: expr.span, kind })
     }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 365e4cbb55676..10fc150017842 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1270,6 +1270,26 @@ impl fmt::Debug for DotDotPos {
     }
 }
 
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub struct PatLit<'hir> {
+    pub hir_id: HirId,
+    pub span: Span,
+    pub kind: PatLitKind<'hir>,
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub enum PatLitKind<'hir> {
+    Lit {
+        lit: &'hir Lit,
+        // FIXME: move this into `Lit` and handle negated literal expressions
+        // once instead of matching on unop neg expressions everywhere.
+        negated: bool,
+    },
+    ConstBlock(ConstBlock),
+    /// A path pattern for a unit struct/variant or a (maybe-associated) constant.
+    Path(QPath<'hir>),
+}
+
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum PatKind<'hir> {
     /// Represents a wildcard pattern (i.e., `_`).
@@ -1315,10 +1335,10 @@ pub enum PatKind<'hir> {
     Ref(&'hir Pat<'hir>, Mutability),
 
     /// A literal.
-    Lit(&'hir Expr<'hir>),
+    Lit(&'hir PatLit<'hir>),
 
     /// A range pattern (e.g., `1..=2` or `1..2`).
-    Range(Option<&'hir Expr<'hir>>, Option<&'hir Expr<'hir>>, RangeEnd),
+    Range(Option<&'hir PatLit<'hir>>, Option<&'hir PatLit<'hir>>, RangeEnd),
 
     /// A slice pattern, `[before_0, ..., before_n, (slice, after_0, ..., after_n)?]`.
     ///
@@ -3833,6 +3853,10 @@ pub enum Node<'hir> {
     OpaqueTy(&'hir OpaqueTy<'hir>),
     Pat(&'hir Pat<'hir>),
     PatField(&'hir PatField<'hir>),
+    /// Needed as its own node with its own HirId for tracking
+    /// the unadjusted type of literals within patterns
+    /// (e.g. byte str literals not being of slice type).
+    PatLit(&'hir PatLit<'hir>),
     Arm(&'hir Arm<'hir>),
     Block(&'hir Block<'hir>),
     LetStmt(&'hir LetStmt<'hir>),
@@ -3889,6 +3913,7 @@ impl<'hir> Node<'hir> {
             | Node::Block(..)
             | Node::Ctor(..)
             | Node::Pat(..)
+            | Node::PatLit(..)
             | Node::Arm(..)
             | Node::LetStmt(..)
             | Node::Crate(..)
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 9abb0870bf0ff..7a0b1a069b2a8 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -343,6 +343,9 @@ pub trait Visitor<'v>: Sized {
     fn visit_pat_field(&mut self, f: &'v PatField<'v>) -> Self::Result {
         walk_pat_field(self, f)
     }
+    fn visit_pat_lit(&mut self, lit: &'v PatLit<'v>) -> Self::Result {
+        walk_pat_lit(self, lit)
+    }
     fn visit_anon_const(&mut self, c: &'v AnonConst) -> Self::Result {
         walk_anon_const(self, c)
     }
@@ -686,10 +689,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V:
             try_visit!(visitor.visit_ident(ident));
             visit_opt!(visitor, visit_pat, optional_subpattern);
         }
-        PatKind::Lit(ref expression) => try_visit!(visitor.visit_expr(expression)),
+        PatKind::Lit(lit) => try_visit!(visitor.visit_pat_lit(lit)),
         PatKind::Range(ref lower_bound, ref upper_bound, _) => {
-            visit_opt!(visitor, visit_expr, lower_bound);
-            visit_opt!(visitor, visit_expr, upper_bound);
+            visit_opt!(visitor, visit_pat_lit, lower_bound);
+            visit_opt!(visitor, visit_pat_lit, upper_bound);
         }
         PatKind::Never | PatKind::Wild | PatKind::Err(_) => (),
         PatKind::Slice(prepatterns, ref slice_pattern, postpatterns) => {
@@ -707,6 +710,15 @@ pub fn walk_pat_field<'v, V: Visitor<'v>>(visitor: &mut V, field: &'v PatField<'
     visitor.visit_pat(field.pat)
 }
 
+pub fn walk_pat_lit<'v, V: Visitor<'v>>(visitor: &mut V, lit: &'v PatLit<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(lit.hir_id));
+    match &lit.kind {
+        PatLitKind::Lit { .. } => V::Result::output(),
+        PatLitKind::ConstBlock(c) => visitor.visit_inline_const(c),
+        PatLitKind::Path(qpath) => visitor.visit_qpath(qpath, lit.hir_id, lit.span),
+    }
+}
+
 pub fn walk_anon_const<'v, V: Visitor<'v>>(visitor: &mut V, constant: &'v AnonConst) -> V::Result {
     try_visit!(visitor.visit_id(constant.hir_id));
     visitor.visit_nested_body(constant.body)
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 09e46517cea8b..f9e9b43abde75 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2430,17 +2430,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         Ty::new_error(tcx, err)
                     }
                     hir::PatKind::Range(start, end, include_end) => {
-                        let expr_to_const = |expr: &'tcx hir::Expr<'tcx>| -> ty::Const<'tcx> {
-                            let (expr, neg) = match expr.kind {
-                                hir::ExprKind::Unary(hir::UnOp::Neg, negated) => {
-                                    (negated, Some((expr.hir_id, expr.span)))
-                                }
-                                _ => (expr, None),
-                            };
-                            let (c, c_ty) = match &expr.kind {
-                                hir::ExprKind::Lit(lit) => {
+                        let expr_to_const = |expr: &'tcx hir::PatLit<'tcx>| -> ty::Const<'tcx> {
+                            let (c, c_ty) = match expr.kind {
+                                hir::PatLitKind::Lit { lit, negated } => {
                                     let lit_input =
-                                        LitToConstInput { lit: &lit.node, ty, neg: neg.is_some() };
+                                        LitToConstInput { lit: &lit.node, ty, neg: negated };
                                     let ct = match tcx.lit_to_const(lit_input) {
                                         Ok(c) => c,
                                         Err(LitToConstError::Reported(err)) => {
@@ -2451,23 +2445,30 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                     (ct, ty)
                                 }
 
-                                hir::ExprKind::Path(hir::QPath::Resolved(
+                                hir::PatLitKind::Path(hir::QPath::Resolved(
                                     _,
                                     path @ &hir::Path {
                                         res: Res::Def(DefKind::ConstParam, def_id),
                                         ..
                                     },
                                 )) => {
-                                    let _ = self.prohibit_generic_args(
+                                    match self.prohibit_generic_args(
                                         path.segments.iter(),
                                         GenericsArgsErrExtend::Param(def_id),
-                                    );
-                                    let ty = tcx
-                                        .type_of(def_id)
-                                        .no_bound_vars()
-                                        .expect("const parameter types cannot be generic");
-                                    let ct = self.lower_const_param(def_id, expr.hir_id);
-                                    (ct, ty)
+                                    ) {
+                                        Ok(()) => {
+                                            let ty = tcx
+                                                .type_of(def_id)
+                                                .no_bound_vars()
+                                                .expect("const parameter types cannot be generic");
+                                            let ct = self.lower_const_param(def_id, expr.hir_id);
+                                            (ct, ty)
+                                        }
+                                        Err(guar) => (
+                                            ty::Const::new_error(tcx, guar),
+                                            Ty::new_error(tcx, guar),
+                                        ),
+                                    }
                                 }
 
                                 _ => {
@@ -2478,9 +2479,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                 }
                             };
                             self.record_ty(expr.hir_id, c_ty, expr.span);
-                            if let Some((id, span)) = neg {
-                                self.record_ty(id, c_ty, span);
-                            }
                             c
                         };
 
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index a74e36c45c6ef..075391d0bcaa4 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -98,6 +98,7 @@ impl<'a> State<'a> {
             Node::OpaqueTy(o) => self.print_opaque_ty(o),
             Node::Pat(a) => self.print_pat(a),
             Node::PatField(a) => self.print_patfield(a),
+            Node::PatLit(a) => self.print_pat_lit(a),
             Node::Arm(a) => self.print_arm(a),
             Node::Infer(_) => self.word("_"),
             Node::PreciseCapturingNonLifetimeArg(param) => self.print_ident(param.ident),
@@ -1715,6 +1716,19 @@ impl<'a> State<'a> {
         }
     }
 
+    fn print_pat_lit(&mut self, lit: &hir::PatLit<'_>) {
+        match &lit.kind {
+            hir::PatLitKind::Lit { lit, negated } => {
+                if *negated {
+                    self.word("-");
+                }
+                self.print_literal(lit);
+            }
+            hir::PatLitKind::ConstBlock(c) => self.print_inline_const(c),
+            hir::PatLitKind::Path(qpath) => self.print_qpath(qpath, true),
+        }
+    }
+
     fn print_pat(&mut self, pat: &hir::Pat<'_>) {
         self.maybe_print_comment(pat.span.lo());
         self.ann.pre(self, AnnNode::Pat(pat));
@@ -1832,17 +1846,17 @@ impl<'a> State<'a> {
                     self.pclose();
                 }
             }
-            PatKind::Lit(e) => self.print_expr(e),
+            PatKind::Lit(e) => self.print_pat_lit(e),
             PatKind::Range(begin, end, end_kind) => {
                 if let Some(expr) = begin {
-                    self.print_expr(expr);
+                    self.print_pat_lit(expr);
                 }
                 match end_kind {
                     RangeEnd::Included => self.word("..."),
                     RangeEnd::Excluded => self.word(".."),
                 }
                 if let Some(expr) = end {
-                    self.print_expr(expr);
+                    self.print_pat_lit(expr);
                 }
             }
             PatKind::Slice(before, slice, after) => {
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index c34739de967bf..9e4e285580b4b 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -421,6 +421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | hir::Node::AssocItemConstraint(_)
             | hir::Node::TraitRef(_)
             | hir::Node::PatField(_)
+            | hir::Node::PatLit(_)
             | hir::Node::LetStmt(_)
             | hir::Node::Synthetic
             | hir::Node::Err(_)
@@ -1693,7 +1694,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn check_expr_const_block(
+    pub(super) fn check_expr_const_block(
         &self,
         block: &'tcx hir::ConstBlock,
         expected: Expectation<'tcx>,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index a6276a2e94b6b..ee0125a40e9ac 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -1017,6 +1017,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 def_id,
                 span,
             ),
+            Res::Err => {
+                return (
+                    Ty::new_error(
+                        tcx,
+                        tcx.dcx().span_delayed_bug(span, "could not resolve path {:?}"),
+                    ),
+                    res,
+                );
+            }
             _ => bug!("instantiate_value_path on {:?}", res),
         };
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 6b1a288510ac1..0148aebaf9b27 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -171,6 +171,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 span,
                 ..
             })
+            | hir::Node::PatLit(&hir::PatLit {
+                kind: hir::PatLitKind::Path(QPath::TypeRelative(rcvr, segment)),
+                span,
+                ..
+            })
             | hir::Node::Pat(&hir::Pat {
                 kind:
                     hir::PatKind::Path(QPath::TypeRelative(rcvr, segment))
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index aa853d5e15457..e56c2658bdfab 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -27,6 +27,7 @@ use tracing::{debug, instrument, trace};
 use ty::VariantDef;
 
 use super::report_unexpected_variant_res;
+use crate::expectation::Expectation;
 use crate::gather_locals::DeclOrigin;
 use crate::{FnCtxt, LoweredTy, errors};
 
@@ -368,7 +369,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // 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::Lit(lt) => match self.resolve_vars_if_possible(self.check_expr(lt)).kind() {
+            PatKind::Lit(lt) => match self.resolve_vars_if_possible(self.check_pat_lit_unadjusted(lt)).kind() {
                 ty::Ref(..) => AdjustMode::Pass,
                 _ => AdjustMode::Peel,
             },
@@ -461,10 +462,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         (expected, def_br, max_ref_mutbl)
     }
 
+    fn check_pat_lit_unadjusted(&self, lt: &'tcx hir::PatLit<'tcx>) -> Ty<'tcx> {
+        let ty = match &lt.kind {
+            rustc_hir::PatLitKind::Lit { lit, .. } => {
+                self.check_expr_lit(lit, Expectation::NoExpectation)
+            }
+            rustc_hir::PatLitKind::ConstBlock(c) => {
+                self.check_expr_const_block(c, Expectation::NoExpectation)
+            }
+            rustc_hir::PatLitKind::Path(qpath) => {
+                let (res, opt_ty, segments) =
+                    self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span);
+                self.instantiate_value_path(segments, opt_ty, res, lt.span, lt.span, lt.hir_id).0
+            }
+        };
+        self.write_ty(lt.hir_id, ty);
+        ty
+    }
+
     fn check_pat_lit(
         &self,
         span: Span,
-        lt: &hir::Expr<'tcx>,
+        lt: &hir::PatLit<'tcx>,
         expected: Ty<'tcx>,
         ti: &TopInfo<'tcx>,
     ) -> Ty<'tcx> {
@@ -475,7 +494,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // Byte string patterns behave the same way as array patterns
         // They can denote both statically and dynamically-sized byte arrays.
         let mut pat_ty = ty;
-        if let hir::ExprKind::Lit(Spanned { node: ast::LitKind::ByteStr(..), .. }) = lt.kind {
+        if let hir::PatLitKind::Lit {
+            lit: Spanned { node: ast::LitKind::ByteStr(..), .. }, ..
+        } = lt.kind
+        {
             let expected = self.structurally_resolve_type(span, expected);
             if let ty::Ref(_, inner_ty, _) = *expected.kind()
                 && self.try_structurally_resolve_type(span, inner_ty).is_slice()
@@ -492,7 +514,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if self.tcx.features().string_deref_patterns()
-            && let hir::ExprKind::Lit(Spanned { node: ast::LitKind::Str(..), .. }) = lt.kind
+            && let hir::PatLitKind::Lit { lit: Spanned { node: ast::LitKind::Str(..), .. }, .. } =
+                lt.kind
         {
             let tcx = self.tcx;
             let expected = self.resolve_vars_if_possible(expected);
@@ -533,15 +556,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_range(
         &self,
         span: Span,
-        lhs: Option<&'tcx hir::Expr<'tcx>>,
-        rhs: Option<&'tcx hir::Expr<'tcx>>,
+        lhs: Option<&'tcx hir::PatLit<'tcx>>,
+        rhs: Option<&'tcx hir::PatLit<'tcx>>,
         expected: Ty<'tcx>,
         ti: &TopInfo<'tcx>,
     ) -> Ty<'tcx> {
-        let calc_side = |opt_expr: Option<&'tcx hir::Expr<'tcx>>| match opt_expr {
+        let calc_side = |opt_expr: Option<&'tcx hir::PatLit<'tcx>>| match opt_expr {
             None => None,
             Some(expr) => {
-                let ty = self.check_expr(expr);
+                let ty = self.check_pat_lit_unadjusted(expr);
                 // Check that the end-point is possibly of numeric or char type.
                 // The early check here is not for correctness, but rather better
                 // diagnostics (e.g. when `&str` is being matched, `expected` will
@@ -1780,9 +1803,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 } else if inexistent_fields.len() == 1 {
                     match pat_field.pat.kind {
-                        PatKind::Lit(expr)
+                        PatKind::Lit(_)
                             if !self.may_coerce(
-                                self.typeck_results.borrow().expr_ty(expr),
+                                self.typeck_results.borrow().node_type(pat_field.pat.hir_id),
                                 self.field_ty(field.span, field_def, args),
                             ) => {}
                         _ => {
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index b0c020dd7cbed..cce758bfb3959 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -147,15 +147,16 @@ impl<'a, 'tcx> Visitor<'tcx> for InferBorrowKindVisitor<'a, 'tcx> {
                 self.visit_body(body);
                 self.fcx.analyze_closure(expr.hir_id, expr.span, body_id, body, capture_clause);
             }
-            hir::ExprKind::ConstBlock(anon_const) => {
-                let body = self.fcx.tcx.hir().body(anon_const.body);
-                self.visit_body(body);
-            }
             _ => {}
         }
 
         intravisit::walk_expr(self, expr);
     }
+
+    fn visit_inline_const(&mut self, c: &'tcx hir::ConstBlock) {
+        let body = self.fcx.tcx.hir().body(c.body);
+        self.visit_body(body);
+    }
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs
index e17a68c869215..9bf604f5c1554 100644
--- a/compiler/rustc_hir_typeck/src/writeback.rs
+++ b/compiler/rustc_hir_typeck/src/writeback.rs
@@ -247,6 +247,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             }
         }
     }
+
+    fn visit_const_block(&mut self, span: Span, anon_const: &hir::ConstBlock) {
+        self.visit_node_id(span, anon_const.hir_id);
+
+        let body = self.tcx().hir().body(anon_const.body);
+        self.visit_body(body);
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -276,11 +283,8 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
             hir::ExprKind::Field(..) | hir::ExprKind::OffsetOf(..) => {
                 self.visit_field_id(e.hir_id);
             }
-            hir::ExprKind::ConstBlock(anon_const) => {
-                self.visit_node_id(e.span, anon_const.hir_id);
-
-                let body = self.tcx().hir().body(anon_const.body);
-                self.visit_body(body);
+            hir::ExprKind::ConstBlock(ref anon_const) => {
+                self.visit_const_block(e.span, anon_const);
             }
             _ => {}
         }
@@ -336,6 +340,14 @@ impl<'cx, 'tcx> Visitor<'tcx> for WritebackCx<'cx, 'tcx> {
         intravisit::walk_pat(self, p);
     }
 
+    fn visit_pat_lit(&mut self, lit: &'tcx hir::PatLit<'tcx>) {
+        self.visit_node_id(lit.span, lit.hir_id);
+        if let hir::PatLitKind::ConstBlock(c) = &lit.kind {
+            self.visit_const_block(lit.span, c);
+        }
+        intravisit::walk_pat_lit(self, lit);
+    }
+
     fn visit_local(&mut self, l: &'tcx hir::LetStmt<'tcx>) {
         intravisit::walk_local(self, l);
         let var_ty = self.fcx.local_ty(l.span, l.hir_id);
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 0c701c834f27e..667b3d1ccdf43 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -939,6 +939,7 @@ impl<'hir> Map<'hir> {
             Node::OpaqueTy(op) => op.span,
             Node::Pat(pat) => pat.span,
             Node::PatField(field) => field.span,
+            Node::PatLit(lit) => lit.span,
             Node::Arm(arm) => arm.span,
             Node::Block(block) => block.span,
             Node::Ctor(..) => self.span_with_body(self.tcx.parent_hir_id(hir_id)),
@@ -1210,6 +1211,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
         Node::OpaqueTy(_) => node_str("opaque type"),
         Node::Pat(_) => node_str("pat"),
         Node::PatField(_) => node_str("pattern field"),
+        Node::PatLit(_) => node_str("pattern literal"),
         Node::Param(_) => node_str("param"),
         Node::Arm(_) => node_str("arm"),
         Node::Block(_) => node_str("block"),
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 2dbc8b7b57385..e01827125e375 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -140,7 +140,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
     fn lower_pattern_range_endpoint(
         &mut self,
-        expr: Option<&'tcx hir::Expr<'tcx>>,
+        expr: Option<&'tcx hir::PatLit<'tcx>>,
     ) -> Result<
         (Option<PatRangeBoundary<'tcx>>, Option<Ascription<'tcx>>, Option<LocalDefId>),
         ErrorGuaranteed,
@@ -186,13 +186,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     /// This is only called when the range is already known to be malformed.
     fn error_on_literal_overflow(
         &self,
-        expr: Option<&'tcx hir::Expr<'tcx>>,
+        expr: Option<&'tcx hir::PatLit<'tcx>>,
         ty: Ty<'tcx>,
     ) -> Result<(), ErrorGuaranteed> {
-        use hir::{ExprKind, UnOp};
         use rustc_ast::ast::LitKind;
 
-        let Some(mut expr) = expr else {
+        let Some(expr) = expr else {
             return Ok(());
         };
         let span = expr.span;
@@ -200,12 +199,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         // We need to inspect the original expression, because if we only inspect the output of
         // `eval_bits`, an overflowed value has already been wrapped around.
         // We mostly copy the logic from the `rustc_lint::OVERFLOWING_LITERALS` lint.
-        let mut negated = false;
-        if let ExprKind::Unary(UnOp::Neg, sub_expr) = expr.kind {
-            negated = true;
-            expr = sub_expr;
-        }
-        let ExprKind::Lit(lit) = expr.kind else {
+        let hir::PatLitKind::Lit { lit, negated } = expr.kind else {
             return Ok(());
         };
         let LitKind::Int(lit_val, _) = lit.node else {
@@ -234,8 +228,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
     fn lower_pattern_range(
         &mut self,
-        lo_expr: Option<&'tcx hir::Expr<'tcx>>,
-        hi_expr: Option<&'tcx hir::Expr<'tcx>>,
+        lo_expr: Option<&'tcx hir::PatLit<'tcx>>,
+        hi_expr: Option<&'tcx hir::PatLit<'tcx>>,
         end: RangeEnd,
         ty: Ty<'tcx>,
         span: Span,
@@ -644,25 +638,18 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     /// The special case for negation exists to allow things like `-128_i8`
     /// which would overflow if we tried to evaluate `128_i8` and then negate
     /// afterwards.
-    fn lower_lit(&mut self, expr: &'tcx hir::Expr<'tcx>) -> PatKind<'tcx> {
-        let (lit, neg) = match expr.kind {
-            hir::ExprKind::Path(ref qpath) => {
+    fn lower_lit(&mut self, expr: &'tcx hir::PatLit<'tcx>) -> PatKind<'tcx> {
+        let (lit, neg) = match &expr.kind {
+            hir::PatLitKind::Path(qpath) => {
                 return self.lower_path(qpath, expr.hir_id, expr.span).kind;
             }
-            hir::ExprKind::ConstBlock(ref anon_const) => {
+            hir::PatLitKind::ConstBlock(anon_const) => {
                 return self.lower_inline_const(anon_const, expr.hir_id, expr.span);
             }
-            hir::ExprKind::Lit(ref lit) => (lit, false),
-            hir::ExprKind::Unary(hir::UnOp::Neg, ref expr) => {
-                let hir::ExprKind::Lit(ref lit) = expr.kind else {
-                    span_bug!(expr.span, "not a literal: {:?}", expr);
-                };
-                (lit, true)
-            }
-            _ => span_bug!(expr.span, "not a literal: {:?}", expr),
+            hir::PatLitKind::Lit { lit, negated } => (lit, *negated),
         };
 
-        let ct_ty = self.typeck_results.expr_ty(expr);
+        let ct_ty = self.typeck_results.node_type(expr.hir_id);
         let lit_input = LitToConstInput { lit: &lit.node, ty: ct_ty, neg };
         match self.tcx.at(expr.span).lit_to_const(lit_input) {
             Ok(constant) => self.const_to_pat(constant, ct_ty, expr.hir_id, lit.span).kind,
diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
index 6819ad547f876..17a020850a382 100644
--- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
+++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs
@@ -3,8 +3,8 @@ use clippy_utils::numeric_literal;
 use clippy_utils::source::snippet_opt;
 use rustc_ast::ast::{LitFloatType, LitIntType, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt};
-use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind, StructTailExpr};
+use rustc_hir::intravisit::{Visitor, walk_expr, walk_stmt, walk_pat};
+use rustc_hir::{Block, Body, ConstContext, Expr, ExprKind, FnRetTy, HirId, Lit, Stmt, StmtKind, StructTailExpr, Pat, PatLit, PatKind, PatLitKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_middle::ty::{self, FloatTy, IntTy, PolyFnSig, Ty};
@@ -218,6 +218,18 @@ impl<'tcx> Visitor<'tcx> for NumericFallbackVisitor<'_, 'tcx> {
         walk_expr(self, expr);
     }
 
+    fn visit_pat(&mut self, pat: &'tcx Pat<'_>) {
+        match pat.kind {
+            PatKind::Lit(&PatLit { hir_id, kind: PatLitKind::Lit { lit, .. }, .. }) => {
+                let ty = self.cx.typeck_results().node_type(hir_id);
+                self.check_lit(lit, ty, hir_id);
+                return;
+            }
+            _ => {},
+        }
+        walk_pat(self, pat)
+    }
+
     fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) {
         match stmt.kind {
             // we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric`
diff --git a/src/tools/clippy/clippy_lints/src/len_zero.rs b/src/tools/clippy/clippy_lints/src/len_zero.rs
index 3ea758e176f0b..cf612bf40dfa0 100644
--- a/src/tools/clippy/clippy_lints/src/len_zero.rs
+++ b/src/tools/clippy/clippy_lints/src/len_zero.rs
@@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, DefIdSet};
 use rustc_hir::{
     AssocItemKind, BinOpKind, Expr, ExprKind, FnRetTy, GenericArg, GenericBound, ImplItem, ImplItemKind,
     ImplicitSelfKind, Item, ItemKind, Mutability, Node, OpaqueTyOrigin, PatKind, PathSegment, PrimTy, QPath,
-    TraitItemRef, TyKind,
+    TraitItemRef, TyKind, PatLitKind,
 };
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty::{self, AssocKind, FnSig, Ty};
@@ -163,7 +163,13 @@ impl<'tcx> LateLintPass<'tcx> for LenZero {
         if let ExprKind::Let(lt) = expr.kind
             && match lt.pat.kind {
                 PatKind::Slice([], None, []) => true,
-                PatKind::Lit(lit) if is_empty_string(lit) => true,
+                PatKind::Lit(lit) => match lit.kind {
+                    PatLitKind::Lit { lit, .. } => match lit.node {
+                        LitKind::Str(lit, _) => lit.as_str().is_empty(),
+                        _ => false,
+                    },
+                    _ => false,
+                },
                 _ => false,
             }
             && !expr.span.from_expansion()
diff --git a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
index 3f01f3cf30aea..b5999f9275757 100644
--- a/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_is_ascii_check.rs
@@ -7,7 +7,7 @@ use clippy_utils::{higher, is_in_const_context, path_to_local, peel_ref_operator
 use rustc_ast::LitKind::{Byte, Char};
 use rustc_ast::ast::RangeLimits;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd};
+use rustc_hir::{Expr, ExprKind, Node, Param, PatKind, RangeEnd, PatLit, PatLitKind, Lit};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
@@ -115,7 +115,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualIsAsciiCheck {
         {
             let arg = peel_ref_operators(cx, arg);
             let ty_sugg = get_ty_sugg(cx, arg, start);
-            let range = check_range(start, end);
+            let range = check_expr_range(start, end);
             check_is_ascii(cx, expr.span, arg, &range, ty_sugg);
         }
     }
@@ -196,19 +196,34 @@ fn check_pat(pat_kind: &PatKind<'_>) -> CharRange {
     }
 }
 
-fn check_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
+fn check_expr_range(start: &Expr<'_>, end: &Expr<'_>) -> CharRange {
     if let ExprKind::Lit(start_lit) = &start.kind
         && let ExprKind::Lit(end_lit) = &end.kind
     {
-        match (&start_lit.node, &end_lit.node) {
-            (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
-            (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
-            (Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter,
-            (Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter,
-            (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
-            _ => CharRange::Otherwise,
-        }
+        check_lit_range(start_lit, end_lit)
+    } else {
+        CharRange::Otherwise
+    }
+}
+
+
+fn check_range(start: &PatLit<'_>, end: &PatLit<'_>) -> CharRange {
+    if let PatLitKind::Lit{ lit: start_lit, negated: false } = &start.kind
+        && let PatLitKind::Lit{ lit: end_lit, negated: false  } = &end.kind
+    {
+        check_lit_range(start_lit, end_lit)
     } else {
         CharRange::Otherwise
     }
 }
+
+fn check_lit_range(start_lit: &Lit, end_lit: &Lit) -> CharRange {
+    match (&start_lit.node, &end_lit.node) {
+        (Char('a'), Char('z')) | (Byte(b'a'), Byte(b'z')) => CharRange::LowerChar,
+        (Char('A'), Char('Z')) | (Byte(b'A'), Byte(b'Z')) => CharRange::UpperChar,
+        (Char('a'), Char('f')) | (Byte(b'a'), Byte(b'f')) => CharRange::LowerHexLetter,
+        (Char('A'), Char('F')) | (Byte(b'A'), Byte(b'F')) => CharRange::UpperHexLetter,
+        (Char('0'), Char('9')) | (Byte(b'0'), Byte(b'9')) => CharRange::Digit,
+        _ => CharRange::Otherwise,
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
index ffa3eacf3544f..bf324a9e5219e 100644
--- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs
@@ -3,7 +3,7 @@ use clippy_utils::source::SpanRangeExt;
 use rustc_ast::LitKind;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, PatKind, RangeEnd, UnOp};
+use rustc_hir::{PatLit, PatLitKind, PatKind, RangeEnd};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
 use rustc_session::declare_lint_pass;
@@ -38,14 +38,13 @@ declare_clippy_lint! {
 }
 declare_lint_pass!(ManualRangePatterns => [MANUAL_RANGE_PATTERNS]);
 
-fn expr_as_i128(expr: &Expr<'_>) -> Option<i128> {
-    if let ExprKind::Unary(UnOp::Neg, expr) = expr.kind {
-        expr_as_i128(expr).map(|num| -num)
-    } else if let ExprKind::Lit(lit) = expr.kind
+fn expr_as_i128(expr: &PatLit<'_>) -> Option<i128> {
+    if let PatLitKind::Lit { lit, negated } = expr.kind
         && let LitKind::Int(num, _) = lit.node
     {
         // Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now.
-        num.get().try_into().ok()
+        let n = i128::try_from(num.get()).ok()?;
+        Some(if negated { -n } else { n })
     } else {
         None
     }
@@ -58,7 +57,7 @@ struct Num {
 }
 
 impl Num {
-    fn new(expr: &Expr<'_>) -> Option<Self> {
+    fn new(expr: &PatLit<'_>) -> Option<Self> {
         Some(Self {
             val: expr_as_i128(expr)?,
             span: expr.span,
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
index 69105ff0d5c7a..d44ac6330431c 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_bool.rs
@@ -4,7 +4,7 @@ use clippy_utils::source::{expr_block, snippet};
 use clippy_utils::sugg::Sugg;
 use rustc_ast::LitKind;
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, Expr, ExprKind, PatKind};
+use rustc_hir::{Arm, Expr, PatLitKind, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 
@@ -22,7 +22,7 @@ pub(crate) fn check(cx: &LateContext<'_>, scrutinee: &Expr<'_>, arms: &[Arm<'_>]
                 if arms.len() == 2 {
                     // no guards
                     let exprs = if let PatKind::Lit(arm_bool) = arms[0].pat.kind {
-                        if let ExprKind::Lit(lit) = arm_bool.kind {
+                        if let PatLitKind::Lit { lit, .. } = arm_bool.kind {
                             match lit.node {
                                 LitKind::Bool(true) => Some((arms[0].body, arms[1].body)),
                                 LitKind::Bool(false) => Some((arms[1].body, arms[0].body)),
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 20984bc40caf3..6403afc9cc38c 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_arena::DroplessArena;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd};
+use rustc_hir::{Arm, Expr, PatLitKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd};
 use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
@@ -315,7 +315,7 @@ impl<'a> NormalizedPat<'a> {
             },
             PatKind::Lit(e) => match &e.kind {
                 // TODO: Handle negative integers. They're currently treated as a wild match.
-                ExprKind::Lit(lit) => match lit.node {
+                PatLitKind::Lit{ lit, negated: false } => match lit.node {
                     LitKind::Str(sym, _) => Self::LitStr(sym),
                     LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes),
                     LitKind::Byte(val) => Self::LitInt(val.into()),
@@ -332,7 +332,7 @@ impl<'a> NormalizedPat<'a> {
                 let start = match start {
                     None => 0,
                     Some(e) => match &e.kind {
-                        ExprKind::Lit(lit) => match lit.node {
+                        PatLitKind::Lit { lit, negated: false } => match lit.node {
                             LitKind::Int(val, _) => val.get(),
                             LitKind::Char(val) => val.into(),
                             LitKind::Byte(val) => val.into(),
@@ -344,7 +344,7 @@ impl<'a> NormalizedPat<'a> {
                 let (end, bounds) = match end {
                     None => (u128::MAX, RangeEnd::Included),
                     Some(e) => match &e.kind {
-                        ExprKind::Lit(lit) => match lit.node {
+                        PatLitKind::Lit { lit, negated: false } => match lit.node {
                             LitKind::Int(val, _) => (val.get(), bounds),
                             LitKind::Char(val) => (val.into(), bounds),
                             LitKind::Byte(val) => (val.into(), bounds),
diff --git a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
index 1267fc9d0a531..54727c8a044bc 100644
--- a/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/match_str_case_mismatch.rs
@@ -5,7 +5,7 @@ use clippy_utils::ty::is_type_lang_item;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{Visitor, walk_expr};
-use rustc_hir::{Arm, Expr, ExprKind, LangItem, PatKind};
+use rustc_hir::{Arm, Expr, ExprKind, PatLit, PatLitKind, LangItem, PatKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
 use rustc_span::Span;
@@ -85,8 +85,8 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<(
     };
 
     for arm in arms {
-        if let PatKind::Lit(Expr {
-            kind: ExprKind::Lit(lit),
+        if let PatKind::Lit(PatLit {
+            kind: PatLitKind::Lit { lit, negated: false },
             ..
         }) = arm.pat.kind
             && let LitKind::Str(symbol, _) = lit.node
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 6f7d690264049..07c269bb5d4bc 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,7 @@ use clippy_utils::{
 };
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatKind, Path, QPath};
+use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatKind, Path, QPath, PatLitKind};
 use rustc_lint::LateContext;
 use rustc_span::sym;
 
@@ -188,7 +188,7 @@ fn pat_same_as_expr(pat: &Pat<'_>, expr: &Expr<'_>) -> bool {
         },
         // Example: `5 => 5`
         (PatKind::Lit(pat_lit_expr), ExprKind::Lit(expr_spanned)) => {
-            if let ExprKind::Lit(pat_spanned) = &pat_lit_expr.kind {
+            if let PatLitKind::Lit { lit: pat_spanned, negated: false } = &pat_lit_expr.kind {
                 return pat_spanned.node == expr_spanned.node;
             }
         },
diff --git a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
index 856311899f268..05d75637babc4 100644
--- a/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/overlapping_arms.rs
@@ -34,13 +34,13 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
             if let Arm { pat, guard: None, .. } = *arm {
                 if let PatKind::Range(ref lhs, ref rhs, range_end) = pat.kind {
                     let lhs_const = if let Some(lhs) = lhs {
-                        ConstEvalCtxt::new(cx).eval(lhs)?
+                        ConstEvalCtxt::new(cx).eval_pat_lit(lhs)?
                     } else {
                         let min_val_const = ty.numeric_min_val(cx.tcx)?;
                         mir_to_const(cx.tcx, mir::Const::from_ty_const(min_val_const, ty, cx.tcx))?
                     };
                     let rhs_const = if let Some(rhs) = rhs {
-                        ConstEvalCtxt::new(cx).eval(rhs)?
+                        ConstEvalCtxt::new(cx).eval_pat_lit(rhs)?
                     } else {
                         let max_val_const = ty.numeric_max_val(cx.tcx)?;
                         mir_to_const(cx.tcx, mir::Const::from_ty_const(max_val_const, ty, cx.tcx))?
@@ -58,7 +58,7 @@ fn all_ranges<'tcx>(cx: &LateContext<'tcx>, arms: &'tcx [Arm<'_>], ty: Ty<'tcx>)
                 }
 
                 if let PatKind::Lit(value) = pat.kind {
-                    let value = ConstEvalCtxt::new(cx).eval_full_int(value)?;
+                    let value = ConstEvalCtxt::new(cx).eval_pat_lit(value)?.int_value(cx.tcx, cx.typeck_results().node_type(pat.hir_id))?;
                     return Some(SpannedRange {
                         span: pat.span,
                         node: (value, EndBound::Included(value)),
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 264458a86ef49..52ff2eb1ff3ad 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_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp};
+use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp, PatLitKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, GenericArgKind, Ty};
 use rustc_span::{Span, Symbol, sym};
@@ -75,7 +75,7 @@ fn find_match_true<'tcx>(
     message: &'static str,
 ) {
     if let PatKind::Lit(lit) = pat.kind
-        && let ExprKind::Lit(lit) = lit.kind
+        && let PatLitKind::Lit{ lit, negated: false } = lit.kind
         && let LitKind::Bool(pat_is_true) = lit.node
     {
         let mut applicability = Applicability::MachineApplicable;
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 95a4bf6f60de3..33d3cd5e9a054 100644
--- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs
+++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs
@@ -9,7 +9,7 @@ use rustc_arena::DroplessArena;
 use rustc_errors::Applicability;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::intravisit::{Visitor, walk_pat};
-use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind};
+use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatKind, QPath, StmtKind, PatLit, PatLitKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef};
 use rustc_span::{Span, sym};
@@ -126,8 +126,8 @@ fn report_single_pattern(cx: &LateContext<'_>, ex: &Expr<'_>, arm: &Arm<'_>, exp
         // scrutinee derives PartialEq and the pattern is a constant.
         let pat_ref_count = match pat.kind {
             // string literals are already a reference.
-            PatKind::Lit(Expr {
-                kind: ExprKind::Lit(lit),
+            PatKind::Lit(PatLit {
+                kind: PatLitKind::Lit { lit, negated: false },
                 ..
             }) if lit.node.is_str() => pat_ref_count + 1,
             _ => pat_ref_count,
diff --git a/src/tools/clippy/clippy_lints/src/string_patterns.rs b/src/tools/clippy/clippy_lints/src/string_patterns.rs
index 0d85b1b858a4f..c29bdbd8cf6ae 100644
--- a/src/tools/clippy/clippy_lints/src/string_patterns.rs
+++ b/src/tools/clippy/clippy_lints/src/string_patterns.rs
@@ -11,7 +11,7 @@ use clippy_utils::visitors::{Descend, for_each_expr};
 use itertools::Itertools;
 use rustc_ast::{BinOpKind, LitKind};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, PatKind};
+use rustc_hir::{Expr, ExprKind, PatKind, PatLitKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::impl_lint_pass;
@@ -171,7 +171,7 @@ fn check_manual_pattern_char_comparison(cx: &LateContext<'_>, method_arg: &Expr<
                         return ControlFlow::Break(());
                     }
                     if arm.pat.walk_short(|pat| match pat.kind {
-                        PatKind::Lit(expr) if let ExprKind::Lit(lit) = expr.kind => {
+                        PatKind::Lit(expr) if let PatLitKind::Lit { lit, negated: false } = expr.kind => {
                             if let LitKind::Char(_) = lit.node {
                                 set_char_spans.push(lit.span);
                             }
diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 311ed427cb910..2d26045652e0a 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -4,7 +4,7 @@ use rustc_ast::ast::{LitFloatType, LitKind};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{
     self as hir, BindingMode, CaptureBy, Closure, ClosureKind, ConstArg, ConstArgKind, CoroutineKind,
-    ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, StructTailExpr,
+    ExprKind, FnRetTy, HirId, Lit, PatKind, QPath, StmtKind, TyKind, StructTailExpr, PatLitKind
 };
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
@@ -640,6 +640,27 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
         self.expr(expr);
     }
 
+    fn pat_lit(&self, lit: &Binding<&hir::PatLit<'_>>) {
+        let kind = |kind| chain!(self, "let PatLitKind::{kind} = {lit}.kind");
+        macro_rules! kind {
+            ($($t:tt)*) => (kind(format_args!($($t)*)));
+        }
+        match lit.value.kind {
+            PatLitKind::Lit { lit, negated } => {
+                bind!(self, lit);
+                bind!(self, negated);
+                kind!("Lit{{ref {lit}, {negated} }}");
+                self.lit(lit);
+            }
+            PatLitKind::ConstBlock(_) => kind!("ConstBlock(_)"),
+            PatLitKind::Path(ref qpath) => {
+                bind!(self, qpath);
+                kind!("Path(ref {qpath})");
+                self.qpath(qpath);
+            }
+        }
+    }
+
     fn pat(&self, pat: &Binding<&hir::Pat<'_>>) {
         let kind = |kind| chain!(self, "let PatKind::{kind} = {pat}.kind");
         macro_rules! kind {
@@ -712,13 +733,13 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
             PatKind::Lit(lit_expr) => {
                 bind!(self, lit_expr);
                 kind!("Lit({lit_expr})");
-                self.expr(lit_expr);
+                self.pat_lit(lit_expr);
             },
             PatKind::Range(start, end, end_kind) => {
                 opt_bind!(self, start, end);
                 kind!("Range({start}, {end}, RangeEnd::{end_kind:?})");
-                start.if_some(|e| self.expr(e));
-                end.if_some(|e| self.expr(e));
+                start.if_some(|e| self.pat_lit(e));
+                end.if_some(|e| self.pat_lit(e));
             },
             PatKind::Slice(start, middle, end) => {
                 bind!(self, start, end);
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 43ddf06730dd2..9e0b2048d2300 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -4,7 +4,6 @@
 //! executable MIR bodies, so we have to do this instead.
 #![allow(clippy::float_cmp)]
 
-use crate::macros::HirNode;
 use crate::source::{SpanRangeExt, walk_span_to_context};
 use crate::{clip, is_direct_expn_of, sext, unsext};
 
@@ -13,7 +12,7 @@ use rustc_apfloat::ieee::{Half, Quad};
 use rustc_ast::ast::{self, LitFloatType, LitKind};
 use rustc_data_structures::sync::Lrc;
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp};
+use rustc_hir::{BinOp, BinOpKind, Block, ConstBlock, Expr, ExprKind, HirId, Item, ItemKind, Node, QPath, UnOp, PatLit, PatLitKind};
 use rustc_lexer::tokenize;
 use rustc_lint::LateContext;
 use rustc_middle::mir::ConstValue;
@@ -442,30 +441,48 @@ impl<'tcx> ConstEvalCtxt<'tcx> {
         }
     }
 
+    pub fn eval_pat_lit(&self, pat_lit: &PatLit<'_>) -> Option<Constant<'tcx>> {
+        match &pat_lit.kind {
+            PatLitKind::Lit { lit, negated } => {
+                let ty = self.typeck.node_type_opt(pat_lit.hir_id);
+                let val = lit_to_mir_constant(&lit.node, ty);
+                if *negated {
+                    self.constant_negate(&val, ty?)
+                } else {
+                    Some(val)
+                }
+            }
+            PatLitKind::ConstBlock(ConstBlock { body, ..}) => self.expr(self.tcx.hir().body(*body).value),
+            PatLitKind::Path(qpath) => self.qpath(qpath, pat_lit.hir_id),
+        }
+    }
+
+    fn qpath(&self, qpath: &QPath<'_>, hir_id: HirId) -> Option<Constant<'tcx>> {
+        let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, hir_id).opt_def_id() {
+            self.tcx.crate_name(def_id.krate) == sym::core
+        } else {
+            false
+        };
+        self.fetch_path_and_apply(qpath, hir_id, self.typeck.node_type(hir_id), |self_, result| {
+            let result = mir_to_const(self_.tcx, result)?;
+            // If source is already Constant we wouldn't want to override it with CoreConstant
+            self_.source.set(
+                if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) {
+                    ConstantSource::CoreConstant
+                } else {
+                    ConstantSource::Constant
+                },
+            );
+            Some(result)
+        })
+    }
+
     /// Simple constant folding: Insert an expression, get a constant or none.
     fn expr(&self, e: &Expr<'_>) -> Option<Constant<'tcx>> {
         match e.kind {
             ExprKind::ConstBlock(ConstBlock { body, .. }) => self.expr(self.tcx.hir().body(body).value),
             ExprKind::DropTemps(e) => self.expr(e),
-            ExprKind::Path(ref qpath) => {
-                let is_core_crate = if let Some(def_id) = self.typeck.qpath_res(qpath, e.hir_id()).opt_def_id() {
-                    self.tcx.crate_name(def_id.krate) == sym::core
-                } else {
-                    false
-                };
-                self.fetch_path_and_apply(qpath, e.hir_id, self.typeck.expr_ty(e), |self_, result| {
-                    let result = mir_to_const(self_.tcx, result)?;
-                    // If source is already Constant we wouldn't want to override it with CoreConstant
-                    self_.source.set(
-                        if is_core_crate && !matches!(self_.source.get(), ConstantSource::Constant) {
-                            ConstantSource::CoreConstant
-                        } else {
-                            ConstantSource::Constant
-                        },
-                    );
-                    Some(result)
-                })
-            },
+            ExprKind::Path(ref qpath) => self.qpath(qpath, e.hir_id),
             ExprKind::Block(block, _) => self.block(block),
             ExprKind::Lit(lit) => {
                 if is_direct_expn_of(e.span, "cfg").is_some() {
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 4be4340862d2a..541753f145623 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -10,7 +10,7 @@ use rustc_hir::{
     AssocItemConstraint, BinOpKind, BindingMode, Block, BodyId, Closure, ConstArg, ConstArgKind, Expr,
     ExprField, ExprKind, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, InlineAsmOperand, LetExpr, Lifetime,
     LifetimeName, Pat, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, TraitBoundModifiers, Ty,
-    TyKind, StructTailExpr,
+    TyKind, StructTailExpr, PatLit, PatLitKind,
 };
 use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::LateContext;
@@ -484,6 +484,15 @@ impl HirEqInterExpr<'_, '_, '_> {
         li.name == ri.name && self.eq_pat(lp, rp)
     }
 
+    fn eq_pat_lit(&mut self, left: &PatLit<'_>, right: &PatLit<'_>) -> bool {
+        match (&left.kind, &right.kind) {
+            (&PatLitKind::Lit { lit: left, negated: left_neg }, &PatLitKind::Lit { lit: right, negated: right_neg}) => left_neg == right_neg && left.node == right.node,
+            (PatLitKind::ConstBlock(left), PatLitKind::ConstBlock(right)) => self.eq_body(left.body, right.body),
+            (PatLitKind::Path(left), PatLitKind::Path(right)) => self.eq_qpath(left, right),
+            (PatLitKind::Lit {..} | PatLitKind::ConstBlock(..) | PatLitKind::Path(..), _) => false,
+        }
+    }
+
     /// Checks whether two patterns are the same.
     fn eq_pat(&mut self, left: &Pat<'_>, right: &Pat<'_>) -> bool {
         match (&left.kind, &right.kind) {
@@ -502,11 +511,11 @@ impl HirEqInterExpr<'_, '_, '_> {
                 eq
             },
             (PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r),
-            (&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_expr(l, r),
+            (&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_pat_lit(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)) => {
-                both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_expr(a, b))
-                    && both(le.as_ref(), re.as_ref(), |a, b| self.eq_expr(a, b))
+                both(ls.as_ref(), rs.as_ref(), |a, b| self.eq_pat_lit(a, b))
+                    && both(le.as_ref(), re.as_ref(), |a, b| self.eq_pat_lit(a, b))
                     && (li == ri)
             },
             (&PatKind::Ref(le, ref lm), &PatKind::Ref(re, ref rm)) => lm == rm && self.eq_pat(le, re),
@@ -1062,6 +1071,18 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
         // self.maybe_typeck_results.unwrap().qpath_res(p, id).hash(&mut self.s);
     }
 
+    pub fn hash_pat_lit(&mut self, lit: &PatLit<'_>) {
+        std::mem::discriminant(&lit.kind).hash(&mut self.s);
+        match &lit.kind {
+            PatLitKind::Lit { lit, negated } => {
+                lit.node.hash(&mut self.s);
+                negated.hash(&mut self.s);
+            }
+            PatLitKind::ConstBlock(c) => self.hash_body(c.body),
+            PatLitKind::Path(qpath) => self.hash_qpath(qpath),
+        }
+    }
+
     pub fn hash_pat(&mut self, pat: &Pat<'_>) {
         std::mem::discriminant(&pat.kind).hash(&mut self.s);
         match pat.kind {
@@ -1073,7 +1094,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                 }
             },
             PatKind::Box(pat) | PatKind::Deref(pat) => self.hash_pat(pat),
-            PatKind::Lit(expr) => self.hash_expr(expr),
+            PatKind::Lit(expr) => self.hash_pat_lit(expr),
             PatKind::Or(pats) => {
                 for pat in pats {
                     self.hash_pat(pat);
@@ -1082,10 +1103,10 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             PatKind::Path(ref qpath) => self.hash_qpath(qpath),
             PatKind::Range(s, e, i) => {
                 if let Some(s) = s {
-                    self.hash_expr(s);
+                    self.hash_pat_lit(s);
                 }
                 if let Some(e) = e {
-                    self.hash_expr(e);
+                    self.hash_pat_lit(e);
                 }
                 std::mem::discriminant(&i).hash(&mut self.s);
             },
diff --git a/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui/author/if.stdout
index a85dcddd3315f..9788f06eef7b1 100644
--- a/src/tools/clippy/tests/ui/author/if.stdout
+++ b/src/tools/clippy/tests/ui/author/if.stdout
@@ -31,7 +31,7 @@ if let StmtKind::Let(local) = stmt.kind
 if let ExprKind::If(cond, then, Some(else_expr)) = expr.kind
     && let ExprKind::Let(let_expr) = cond.kind
     && let PatKind::Lit(lit_expr) = let_expr.pat.kind
-    && let ExprKind::Lit(ref lit) = lit_expr.kind
+    && let PatLitKind::Lit{ref lit, negated } = lit_expr.kind
     && let LitKind::Bool(true) = lit.node
     && let ExprKind::Path(ref qpath) = let_expr.init.kind
     && match_qpath(qpath, &["a"])
diff --git a/src/tools/clippy/tests/ui/author/loop.stdout b/src/tools/clippy/tests/ui/author/loop.stdout
index 609d24910610c..c65ab3cd52533 100644
--- a/src/tools/clippy/tests/ui/author/loop.stdout
+++ b/src/tools/clippy/tests/ui/author/loop.stdout
@@ -77,7 +77,7 @@ if let Some(higher::While { condition: condition, body: body }) = higher::While:
 }
 if let Some(higher::WhileLet { let_pat: let_pat, let_expr: let_expr, if_then: if_then }) = higher::WhileLet::hir(expr)
     && let PatKind::Lit(lit_expr) = let_pat.kind
-    && let ExprKind::Lit(ref lit) = lit_expr.kind
+    && let PatLitKind::Lit{ref lit, negated } = lit_expr.kind
     && let LitKind::Bool(true) = lit.node
     && let ExprKind::Path(ref qpath) = let_expr.kind
     && match_qpath(qpath, &["a"])
diff --git a/src/tools/clippy/tests/ui/author/matches.stdout b/src/tools/clippy/tests/ui/author/matches.stdout
index 91b3b6f6877eb..681615777795e 100644
--- a/src/tools/clippy/tests/ui/author/matches.stdout
+++ b/src/tools/clippy/tests/ui/author/matches.stdout
@@ -5,13 +5,13 @@ if let StmtKind::Let(local) = stmt.kind
     && let LitKind::Int(42, LitIntType::Unsuffixed) = lit.node
     && arms.len() == 3
     && let PatKind::Lit(lit_expr) = arms[0].pat.kind
-    && let ExprKind::Lit(ref lit1) = lit_expr.kind
+    && let PatLitKind::Lit{ref lit1, negated } = lit_expr.kind
     && let LitKind::Int(16, LitIntType::Unsuffixed) = lit1.node
     && arms[0].guard.is_none()
     && let ExprKind::Lit(ref lit2) = arms[0].body.kind
     && let LitKind::Int(5, LitIntType::Unsuffixed) = lit2.node
     && let PatKind::Lit(lit_expr1) = arms[1].pat.kind
-    && let ExprKind::Lit(ref lit3) = lit_expr1.kind
+    && let PatLitKind::Lit{ref lit3, negated1 } = lit_expr1.kind
     && let LitKind::Int(17, LitIntType::Unsuffixed) = lit3.node
     && arms[1].guard.is_none()
     && let ExprKind::Block(block, None) = arms[1].body.kind
diff --git a/src/tools/clippy/tests/ui/author/struct.stdout b/src/tools/clippy/tests/ui/author/struct.stdout
index 0b332d5e7d0e1..79cf56e3d57ca 100644
--- a/src/tools/clippy/tests/ui/author/struct.stdout
+++ b/src/tools/clippy/tests/ui/author/struct.stdout
@@ -24,7 +24,7 @@ if let PatKind::Struct(ref qpath, fields, false) = arm.pat.kind
     && fields.len() == 1
     && fields[0].ident.as_str() == "field"
     && let PatKind::Lit(lit_expr) = fields[0].pat.kind
-    && let ExprKind::Lit(ref lit) = lit_expr.kind
+    && let PatLitKind::Lit{ref lit, negated } = lit_expr.kind
     && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
     && arm.guard.is_none()
     && let ExprKind::Block(block, None) = arm.body.kind
@@ -37,7 +37,7 @@ if let PatKind::TupleStruct(ref qpath, fields, None) = arm.pat.kind
     && match_qpath(qpath, &["TestTuple"])
     && fields.len() == 1
     && let PatKind::Lit(lit_expr) = fields[0].kind
-    && let ExprKind::Lit(ref lit) = lit_expr.kind
+    && let PatLitKind::Lit{ref lit, negated } = lit_expr.kind
     && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node
     && arm.guard.is_none()
     && let ExprKind::Block(block, None) = arm.body.kind
diff --git a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
index c424b1afa3465..43aa93c83bd31 100644
--- a/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
+++ b/tests/ui/unpretty/unpretty-expr-fn-arg.stdout
@@ -14,4 +14,4 @@ extern crate std;
 
 fn main() ({ } as ())
 
-fn foo((-(128 as i8) as i8)...(127 as i8): i8) ({ } as ())
+fn foo(-128...127: i8) ({ } as ())

From 78d2b596fd2484c15705a6326fff031914dc4e80 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github333195615777966@oli-obk.de>
Date: Thu, 12 Dec 2024 10:37:37 +0000
Subject: [PATCH 4/5] Eliminate PatKind::Path

---
 compiler/rustc_ast_lowering/src/expr.rs       |  6 ++-
 compiler/rustc_ast_lowering/src/pat.rs        | 17 ++++--
 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  | 10 ++--
 .../src/fn_ctxt/suggestions.rs                | 10 ++--
 .../rustc_hir_typeck/src/method/suggest.rs    |  3 +-
 compiler/rustc_hir_typeck/src/pat.rs          | 54 +++++++++++--------
 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 +-
 .../clippy_lints/src/equatable_if_let.rs      |  2 +-
 .../clippy_lints/src/manual_let_else.rs       |  4 +-
 .../src/manual_unwrap_or_default.rs           |  4 +-
 .../src/matches/collapsible_match.rs          |  4 +-
 .../src/matches/manual_unwrap_or.rs           |  4 +-
 .../clippy_lints/src/matches/manual_utils.rs  |  4 +-
 .../clippy_lints/src/matches/match_as_ref.rs  |  4 +-
 .../src/matches/match_same_arms.rs            |  4 +-
 .../src/matches/match_wild_enum.rs            |  6 +--
 .../src/matches/needless_match.rs             |  4 +-
 .../src/matches/redundant_pattern_match.rs    | 10 ++--
 .../clippy_lints/src/matches/single_match.rs  |  5 +-
 .../clippy_lints/src/option_if_let_else.rs    |  4 +-
 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      | 16 ++++--
 tests/ui/thir-print/thir-tree-match.stdout    | 52 +++++++++---------
 37 files changed, 155 insertions(+), 140 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index fe8ccca072bfb..403d28df7bf27 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -1384,7 +1384,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         None,
                     );
                     // Destructure like a unit struct.
-                    let unit_struct_pat = hir::PatKind::Path(qpath);
+                    let unit_struct_pat = hir::PatKind::Lit(self.arena.alloc(hir::PatLit {
+                        hir_id: self.lower_node_id(lhs.id),
+                        span: lhs.span,
+                        kind: hir::PatLitKind::Path(qpath),
+                    }));
                     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 25702e3c835cf..8750897da49a4 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -70,7 +70,15 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                             ImplTraitContext::Disallowed(ImplTraitPosition::Path),
                             None,
                         );
-                        break hir::PatKind::Path(qpath);
+                        let kind = hir::PatLitKind::Path(qpath);
+                        let lit = hir::PatLit { hir_id: pat_hir_id, span: pattern.span, kind };
+                        let lit = self.arena.alloc(lit);
+                        return hir::Pat {
+                            hir_id: self.next_id(),
+                            kind: hir::PatKind::Lit(lit),
+                            span: pattern.span,
+                            default_binding_modes: true,
+                        };
                     }
                     PatKind::Struct(qself, path, fields, etc) => {
                         let qpath = self.lower_qpath(
@@ -299,14 +307,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             Some(res) => {
                 let hir_id = self.next_id();
                 let res = self.lower_res(res);
-                hir::PatKind::Path(hir::QPath::Resolved(
+                let kind = hir::PatLitKind::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 lit = hir::PatLit { kind, hir_id: self.next_id(), span: ident.span };
+                let lit = self.arena.alloc(lit);
+                hir::PatKind::Lit(lit)
             }
         }
     }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 10fc150017842..d9ccb64d5ead1 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1137,7 +1137,7 @@ impl<'hir> Pat<'hir> {
 
         use PatKind::*;
         match self.kind {
-            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => true,
+            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Err(_) => true,
             Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(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)),
@@ -1164,7 +1164,7 @@ impl<'hir> Pat<'hir> {
 
         use PatKind::*;
         match self.kind {
-            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Path(_) | Err(_) => {}
+            Wild | Never | Lit(_) | Range(..) | Binding(.., None) | Err(_) => {}
             Box(s) | Deref(s) | Ref(s, _) | Binding(.., Some(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)),
@@ -1317,9 +1317,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<usize>` denotes its position.
     /// `0 <= position <= subpats.len()`
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 7a0b1a069b2a8..ddee06b3ab63d 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -669,9 +669,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 2ebbb4a06b6bf..51ee8f142ac23 100644
--- a/compiler/rustc_hir/src/pat_util.rs
+++ b/compiler/rustc_hir/src/pat_util.rs
@@ -106,7 +106,10 @@ impl hir::Pat<'_> {
         let mut variants = vec![];
         self.walk(|p| match &p.kind {
             PatKind::Or(_) => false,
-            PatKind::Path(hir::QPath::Resolved(_, path))
+            PatKind::Lit(hir::PatLit {
+                kind: hir::PatLitKind::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 b9cb48cafdcd2..2b295c362a1bd 100644
--- a/compiler/rustc_hir_analysis/src/check/region.rs
+++ b/compiler/rustc_hir_analysis/src/check/region.rs
@@ -700,7 +700,6 @@ fn resolve_local<'tcx>(
             | PatKind::Binding(hir::BindingMode(hir::ByRef::No, _), ..)
             | PatKind::Wild
             | PatKind::Never
-            | PatKind::Path(_)
             | PatKind::Lit(_)
             | 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 fd49e7e44398b..e66b0785f5aca 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -36,8 +36,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 kind: hir::ExprKind::Path(hir::QPath::TypeRelative(qself, _)),
                 ..
             })
-            | hir::Node::Pat(hir::Pat {
-                kind: hir::PatKind::Path(hir::QPath::TypeRelative(qself, _)),
+            | hir::Node::PatLit(hir::PatLit {
+                kind: hir::PatLitKind::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 075391d0bcaa4..c05889af5b1e1 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1771,9 +1771,6 @@ impl<'a> State<'a> {
                 }
                 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 9e4e285580b4b..8088e7331cf4e 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -468,7 +468,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             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 27ec2e9e0d482..877f4a101598c 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::def::DefKind;
 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, PatKind, PatLit, PatLitKind};
 use rustc_lint::LateContext;
 use rustc_middle::hir::place::ProjectionKind;
 // Export these here so that Clippy can use them.
@@ -560,11 +559,11 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                         // FIXME(never_patterns): does this do what I expect?
                         needs_to_be_read = true;
                     }
-                    PatKind::Path(qpath) => {
+                    PatKind::Lit(PatLit { kind: PatLitKind::Path(qpath), hir_id, .. }) => {
                         // 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
@@ -1793,8 +1792,7 @@ impl<'tcx, Cx: TypeInformationCtxt<'tcx>, D: Delegate<'tcx>> ExprUseVisitor<'tcx
                 }
             }
 
-            PatKind::Path(_)
-            | PatKind::Binding(.., None)
+            PatKind::Binding(.., None)
             | PatKind::Lit(..)
             | 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 ddcd90a2a9da6..0670cfab4c6ac 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 hir::def_id::LocalDefId;
 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,
+    self as hir, Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind,
+    GenericBound, HirId, Node, PatLit, PatLitKind, Path, QPath, Stmt, StmtKind, TyKind,
+    WherePredicateKind,
 };
 use rustc_hir_analysis::collect::suggest_impl_trait;
 use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
@@ -1427,8 +1427,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // 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::Lit(PatLit { kind: PatLitKind::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 0148aebaf9b27..5c3eaab8b2f35 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -178,8 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             })
             | 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 e56c2658bdfab..4b5b51ab81124 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -10,7 +10,9 @@ use rustc_errors::{
 };
 use rustc_hir::def::{CtorKind, DefKind, Res};
 use rustc_hir::pat_util::EnumerateAndAdjustIterator;
-use rustc_hir::{self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind};
+use rustc_hir::{
+    self as hir, BindingMode, ByRef, HirId, LangItem, Mutability, Pat, PatKind, PatLit, PatLitKind,
+};
 use rustc_infer::infer;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
@@ -225,9 +227,9 @@ impl<'a, 'tcx> FnCtxt<'a, '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 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::Lit(&PatLit { kind: PatLitKind::Path(ref qpath), hir_id, span }) => {
+                Some(self.resolve_ty_and_res_fully_qualified_call(qpath, hir_id, span))
             }
             _ => None,
         };
@@ -246,6 +248,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             PatKind::Wild | PatKind::Err(_) => expected,
             // We allow any type here; we ensure that the type is uninhabited during match checking.
             PatKind::Never => expected,
+            PatKind::Lit(&PatLit { kind: PatLitKind::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::Lit(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) => {
@@ -254,9 +269,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             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)
             }
@@ -364,16 +376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             | 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::Lit(lt) => match self.resolve_vars_if_possible(self.check_pat_lit_unadjusted(lt)).kind() {
-                ty::Ref(..) => AdjustMode::Pass,
-                _ => AdjustMode::Peel,
-            },
-            PatKind::Path(_) => match opt_path_res.unwrap() {
+            PatKind::Lit(PatLit { kind: PatLitKind::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.
@@ -384,6 +387,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // 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::Lit(lt) => match self.resolve_vars_if_possible(self.check_pat_lit_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.
@@ -905,7 +917,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         PatKind::Wild
                         | PatKind::Never
                         | PatKind::Binding(..)
-                        | PatKind::Path(..)
                         | PatKind::Box(..)
                         | PatKind::Deref(_)
                         | PatKind::Ref(..)
@@ -1044,6 +1055,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn check_pat_path(
         &self,
         hir_id: HirId,
+        pat_id: HirId,
         span: Span,
         qpath: &hir::QPath<'_>,
         path_resolution: (Res, Option<LoweredTy<'tcx>>, &'tcx [hir::PathSegment<'tcx>]),
@@ -1101,7 +1113,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         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, span, res, pat_res, pat_ty, segments);
         }
         pat_ty
     }
@@ -1144,7 +1156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn emit_bad_pat_path(
         &self,
         mut e: Diag<'_>,
-        hir_id: HirId,
+        pat_id: HirId,
         pat_span: Span,
         res: Res,
         pat_res: Res,
@@ -1163,7 +1175,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         res.descr(),
                     ),
                 );
-                match self.tcx.parent_hir_node(hir_id) {
+                match self.tcx.parent_hir_node(pat_id) {
                     hir::Node::PatField(..) => {
                         e.span_suggestion_verbose(
                             ident.span.shrink_to_hi(),
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 482650e04e85c..fd931c39aafb7 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -6,7 +6,7 @@ use rustc_hir::def::Res;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{
     BinOp, BinOpKind, Expr, ExprKind, GenericArg, HirId, Impl, Item, ItemKind, Node, Pat, PatKind,
-    Path, PathSegment, QPath, Ty, TyKind,
+    PatLit, PatLitKind, Path, PathSegment, QPath, Ty, TyKind,
 };
 use rustc_middle::ty::{self, GenericArgsRef, Ty as MiddleTy};
 use rustc_session::{declare_lint_pass, declare_tool_lint};
@@ -165,11 +165,9 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
             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::PatLit(PatLit { kind: PatLitKind::Path(qpath), .. })
+                        | Node::Pat(Pat {
+                            kind: PatKind::TupleStruct(qpath, ..) | PatKind::Struct(qpath, ..),
                             ..
                         }) => {
                             if let QPath::TypeRelative(qpath_ty, ..) = qpath
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 4d8ebf2909ef8..e4d1a359276d4 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::{GenericParamKind, PatKind};
+use rustc_hir::{GenericParamKind, PatKind, PatLit, PatLitKind};
 use rustc_middle::ty;
 use rustc_session::config::CrateType;
 use rustc_session::{declare_lint, declare_lint_pass};
@@ -528,7 +528,11 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
 
     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::Lit(PatLit {
+            kind: PatLitKind::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 e01827125e375..fa2618e1fc322 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -318,10 +318,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     .unwrap_or_else(PatKind::Error)
             }
 
-            hir::PatKind::Path(ref qpath) => {
-                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 ecf8d34ad8405..dc0d03637d54b 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -10,11 +10,10 @@ use hir::def_id::{LocalDefIdMap, LocalDefIdSet};
 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, PatKind, PatLit, PatLitKind, TyKind};
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::middle::privacy::Level;
 use rustc_middle::query::Providers;
@@ -637,8 +636,8 @@ impl<'tcx> Visitor<'tcx> for MarkSymbolVisitor<'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::Lit(PatLit { kind: PatLitKind::Path(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 f2a37307ceeb8..9833fec637772 100644
--- a/compiler/rustc_passes/src/input_stats.rs
+++ b/compiler/rustc_passes/src/input_stats.rs
@@ -295,7 +295,6 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> {
             TupleStruct,
             Or,
             Never,
-            Path,
             Tuple,
             Box,
             Deref,
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index d59b4e4081ca4..b0413aa57b657 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::Lit(PatLit { kind: PatLitKind::Path(ref p), .. }) => qpath_to_string(p),
         PatKind::Or(pats) => {
             pats.iter().map(|p| name_from_pat(p).to_string()).collect::<Vec<String>>().join(" | ")
         }
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 fb9f2b1526e38..4bbccd72ae3dd 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 unary_pattern(pat: &Pat<'_>) -> bool {
         PatKind::Struct(_, a, etc) => !etc && a.iter().all(|x| unary_pattern(x.pat)),
         PatKind::Tuple(a, etc) | PatKind::TupleStruct(_, a, etc) => etc.as_opt_usize().is_none() && array_rec(a),
         PatKind::Ref(x, _) | PatKind::Box(x) | PatKind::Deref(x) => unary_pattern(x),
-        PatKind::Path(_) | PatKind::Lit(_) => true,
+        PatKind::Lit(_) => 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 a70955a7c78da..29396abe6b814 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::ty::is_type_diagnostic_item;
 use clippy_utils::{is_lint_allowed, is_never_expr, msrvs, pat_and_expr_can_be_question_mark, peel_blocks};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::Applicability;
-use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind};
+use rustc_hir::{Expr, ExprKind, MatchSource, Pat, PatKind, QPath, Stmt, StmtKind, PatLit, PatLitKind};
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::lint::in_external_macro;
 
@@ -292,7 +292,7 @@ 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::Lit(PatLit { kind: PatLitKind::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 8f8390b6f3f9e..006265e9a4c1f 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, PatKind, QPath, PatLit, PatLitKind};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::ty::GenericArgKind;
 use rustc_session::declare_lint_pass;
@@ -68,7 +68,7 @@ fn get_some<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>) -> Option<HirId> {
 }
 
 fn get_none<'tcx>(cx: &LateContext<'tcx>, arm: &Arm<'tcx>) -> Option<&'tcx Expr<'tcx>> {
-    if let PatKind::Path(QPath::Resolved(_, path)) = arm.pat.kind
+    if let PatKind::Lit(PatLit { kind: PatLitKind::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 99a7b8c74be87..1f76a25cc9333 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 clippy_utils::{
 };
 use rustc_errors::MultiSpan;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{Arm, Expr, HirId, Pat, PatKind};
+use rustc_hir::{Arm, Expr, HirId, Pat, PatKind, PatLitKind, PatLit};
 use rustc_lint::LateContext;
 use rustc_span::Span;
 
@@ -119,7 +119,7 @@ fn arm_is_wild_like(cx: &LateContext<'_>, arm: &Arm<'_>) -> bool {
     }
     match arm.pat.kind {
         PatKind::Binding(..) | PatKind::Wild => true,
-        PatKind::Path(ref qpath) => is_res_lang_ctor(cx, cx.qpath_res(qpath, arm.pat.hir_id), OptionNone),
+        PatKind::Lit(&PatLit { kind: PatLitKind::Path(ref 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_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/matches/manual_unwrap_or.rs
index 59d3752001178..7e2786ec9e224 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 clippy_utils::{is_res_lang_ctor, path_to_local_id, peel_blocks, sugg};
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, ResultErr};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Arm, Expr, Pat, PatKind};
+use rustc_hir::{Arm, Expr, Pat, PatKind, PatLit, PatLitKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::Ty;
 use rustc_span::sym;
@@ -89,7 +89,7 @@ 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::Lit(&PatLit { kind: PatLitKind::Path(ref qpath), hir_id, .. }) => 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 bac5cf88cfbf8..32f386d0096fc 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_ast::util::parser::ExprPrecedence;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome};
 use rustc_hir::def::Res;
-use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath};
+use rustc_hir::{BindingMode, Expr, ExprKind, HirId, Mutability, Pat, PatKind, Path, QPath, PatLit, PatLitKind};
 use rustc_lint::LateContext;
 use rustc_span::{SyntaxContext, sym};
 
@@ -256,7 +256,7 @@ pub(super) fn try_parse_pattern<'tcx>(
         match pat.kind {
             PatKind::Wild => Some(OptionPat::Wild),
             PatKind::Ref(pat, _) => f(cx, pat, ref_count + 1, ctxt),
-            PatKind::Path(ref qpath) if is_res_lang_ctor(cx, cx.qpath_res(qpath, pat.hir_id), OptionNone) => {
+            PatKind::Lit(&PatLit { kind: PatLitKind::Path(ref qpath), hir_id, .. }) if is_res_lang_ctor(cx, cx.qpath_res(qpath, hir_id), OptionNone) => {
                 Some(OptionPat::None)
             },
             PatKind::TupleStruct(ref qpath, [pattern], _)
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 6c123649afc2f..b5364a1df146e 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::diagnostics::span_lint_and_sugg;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{is_res_lang_ctor, path_res, peel_blocks};
 use rustc_errors::Applicability;
-use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath};
+use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, LangItem, Mutability, PatKind, QPath, PatLit, PatLitKind};
 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::Lit(&PatLit { kind: PatLitKind::Path(ref qpath), hir_id, .. }) if is_res_lang_ctor(cx, cx.qpath_res(qpath, 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 6403afc9cc38c..5e4a57efc5387 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_arena::DroplessArena;
 use rustc_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::def_id::DefId;
-use rustc_hir::{Arm, Expr, PatLitKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd};
+use rustc_hir::{Arm, Expr, PatLitKind, HirId, HirIdMap, HirIdMapEntry, HirIdSet, Pat, PatKind, RangeEnd, PatLit};
 use rustc_lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_lint::{LateContext, LintContext};
 use rustc_middle::ty;
@@ -294,7 +294,7 @@ impl<'a> NormalizedPat<'a> {
                 Self::Tuple(var_id, pats)
             },
             PatKind::Or(pats) => Self::Or(arena.alloc_from_iter(pats.iter().map(|pat| Self::from_pat(cx, arena, pat)))),
-            PatKind::Path(ref path) => Self::Path(cx.qpath_res(path, pat.hir_id).opt_def_id()),
+            PatKind::Lit(&PatLit { kind: PatLitKind::Path(ref 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 91e40e4275c07..54b25d42e6772 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::ty::is_type_diagnostic_item;
 use clippy_utils::{is_refutable, peel_hir_pat_refs, recurse_or_patterns};
 use rustc_errors::Applicability;
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::{Arm, Expr, PatKind, PathSegment, QPath, Ty, TyKind};
+use rustc_hir::{Arm, Expr, PatKind, PathSegment, QPath, Ty, TyKind, PatLit, PatLitKind};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, VariantDef};
 use rustc_span::sym;
@@ -60,8 +60,8 @@ 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::Lit(PatLit { kind: PatLitKind::Path(ref path), hir_id, .. }) => {
+                    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 07c269bb5d4bc..ccd94af335518 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,7 @@ use clippy_utils::{
 };
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::OptionNone;
-use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatKind, Path, QPath, PatLitKind};
+use rustc_hir::{Arm, BindingMode, ByRef, Expr, ExprKind, ItemKind, Node, Pat, PatKind, Path, QPath, PatLitKind, PatLit};
 use rustc_lint::LateContext;
 use rustc_span::sym;
 
@@ -181,7 +181,7 @@ 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::Lit(PatLit { kind: PatLitKind::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 52ff2eb1ff3ad..baa8cfa061dce 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_ast::ast::LitKind;
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk};
 use rustc_hir::def::{DefKind, Res};
-use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp, PatLitKind};
+use rustc_hir::{Arm, Expr, ExprKind, Node, Pat, PatKind, QPath, UnOp, PatLitKind, PatLit};
 use rustc_lint::LateContext;
 use rustc_middle::ty::{self, GenericArgKind, Ty};
 use rustc_span::{Span, Symbol, sym};
@@ -149,7 +149,7 @@ fn find_method_and_type<'tcx>(
                 None
             }
         },
-        PatKind::Path(ref path) => {
+        PatKind::Lit(PatLit { kind: PatLitKind::Path(ref path), .. }) => {
             if let Res::Def(DefKind::Ctor(..), ctor_id) = cx.qpath_res(path, check_pat.hir_id)
                 && let Some(variant_id) = cx.tcx.opt_parent(ctor_id)
             {
@@ -349,8 +349,8 @@ fn found_good_method<'tcx>(
                 None
             }
         },
-        (PatKind::TupleStruct(path_left, patterns, _), PatKind::Path(path_right))
-        | (PatKind::Path(path_left), PatKind::TupleStruct(path_right, patterns, _))
+        (PatKind::TupleStruct(path_left, patterns, _), PatKind::Lit(PatLit { kind: PatLitKind::Path(path_right), .. }))
+        | (PatKind::Lit(PatLit { kind: PatLitKind::Path(path_left), .. }), PatKind::TupleStruct(path_right, patterns, _))
             if patterns.len() == 1 =>
         {
             if let PatKind::Wild = patterns[0].kind {
@@ -387,7 +387,7 @@ fn found_good_method<'tcx>(
                 None
             }
         },
-        (PatKind::Path(path_left), PatKind::Wild) => get_good_method(cx, arms, path_left),
+        (PatKind::Lit(PatLit { kind: PatLitKind::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 33d3cd5e9a054..62665ec5e89d6 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::Lit(_) = pat.kind
+    let (msg, sugg) = if let PatKind::Lit(_) = 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,7 +331,7 @@ impl<'a> PatState<'a> {
     #[expect(clippy::similar_names)]
     fn add_pat<'tcx>(&mut self, cx: &'a PatCtxt<'tcx>, pat: &'tcx Pat<'_>) -> bool {
         match pat.kind {
-            PatKind::Path(_)
+            PatKind::Lit(PatLit { kind: PatLitKind::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(),
@@ -382,7 +382,6 @@ impl<'a> PatState<'a> {
             | PatKind::Binding(_, _, _, None)
             | PatKind::Lit(_)
             | 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 6d9e75f51d66e..08d5854efd6c4 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,7 @@ use clippy_utils::{
 use rustc_errors::Applicability;
 use rustc_hir::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk};
 use rustc_hir::def::Res;
-use rustc_hir::{Arm, BindingMode, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath, UnOp};
+use rustc_hir::{Arm, BindingMode, Expr, ExprKind, MatchSource, Mutability, Pat, PatKind, Path, QPath, UnOp, PatLit, PatLitKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_session::declare_lint_pass;
 use rustc_span::SyntaxContext;
@@ -281,7 +281,7 @@ 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::Lit(&PatLit { kind: PatLitKind::Path(ref 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 05c5be0300282..2d5e22354f9a2 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::def_id::LocalDefId;
 use rustc_hir::intravisit::{Visitor, walk_inf, walk_ty};
 use rustc_hir::{
     self as hir, Expr, ExprKind, FnRetTy, FnSig, GenericArgsParentheses, GenericParam, GenericParamKind, HirId, Impl,
-    ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind,
+    ImplItemKind, Item, ItemKind, Pat, PatKind, Path, QPath, Ty, TyKind, PatLit, PatLitKind,
 };
 use rustc_hir_analysis::lower_ty;
 use rustc_lint::{LateContext, LateLintPass};
@@ -257,7 +257,7 @@ impl<'tcx> LateLintPass<'tcx> for UseSelf {
             && self.msrv.meets(msrvs::TYPE_ALIAS_ENUM_VARIANTS)
             && let Some(&StackItem::Check { impl_id, .. }) = self.stack.last()
             // get the path from the pattern
-            && let PatKind::Path(QPath::Resolved(_, path))
+            && let PatKind::Lit(&PatLit { kind: PatLitKind::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 2d26045652e0a..d05771f06401f 100644
--- a/src/tools/clippy/clippy_lints/src/utils/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -705,11 +705,6 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> {
                 self.qpath(qpath);
                 self.slice(fields, |pat| self.pat(pat));
             },
-            PatKind::Path(ref qpath) => {
-                bind!(self, qpath);
-                kind!("Path(ref {qpath})");
-                self.qpath(qpath);
-            },
             PatKind::Tuple(fields, skip_pos) => {
                 bind!(self, fields);
                 kind!("Tuple({fields}, {skip_pos:?})");
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index 541753f145623..05f370bcd42f3 100644
--- a/src/tools/clippy/clippy_utils/src/hir_utils.rs
+++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs
@@ -510,7 +510,6 @@ impl HirEqInterExpr<'_, '_, '_> {
                 }
                 eq
             },
-            (PatKind::Path(l), PatKind::Path(r)) => self.eq_qpath(l, r),
             (&PatKind::Lit(l), &PatKind::Lit(r)) => self.eq_pat_lit(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)) => {
@@ -1100,7 +1099,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
                     self.hash_pat(pat);
                 }
             },
-            PatKind::Path(ref qpath) => self.hash_qpath(qpath),
             PatKind::Range(s, e, i) => {
                 if let Some(s) = s {
                     self.hash_pat_lit(s);
diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs
index 8d48cdd3cbb4f..3784178176c0b 100644
--- a/src/tools/clippy/clippy_utils/src/lib.rs
+++ b/src/tools/clippy/clippy_utils/src/lib.rs
@@ -107,7 +107,7 @@ use rustc_hir::{
     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,
+    TyKind, UnOp, def, PatLit, PatLitKind,
 };
 use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::{LateContext, Level, Lint, LintContext};
@@ -550,7 +550,17 @@ macro_rules! maybe_path {
     };
 }
 maybe_path!(Expr, ExprKind);
-maybe_path!(Pat, PatKind);
+impl<'hir> MaybePath<'hir> for Pat<'hir> {
+    fn hir_id(&self) -> HirId {
+        self.hir_id
+    }
+    fn qpath_opt(&self) -> Option<&QPath<'hir>> {
+        match &self.kind {
+            PatKind::Lit(PatLit { kind: PatLitKind::Path(qpath), .. }) => Some(qpath),
+            _ => None,
+        }
+    }
+}
 maybe_path!(Ty, TyKind);
 
 /// If `maybe_path` is a path node, resolves it, otherwise returns `Res::Err`
@@ -1743,7 +1753,7 @@ pub fn is_refutable(cx: &LateContext<'_>, pat: &Pat<'_>) -> bool {
         PatKind::Wild | PatKind::Never => false, // If `!` typechecked then the type is empty, so not refutable.
         PatKind::Binding(_, _, _, pat) => pat.is_some_and(|pat| is_refutable(cx, pat)),
         PatKind::Box(pat) | PatKind::Ref(pat, _) => is_refutable(cx, pat),
-        PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id),
+        PatKind::Lit(PatLit { kind: PatLitKind::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 916f296ccfc6b..910582ae4d9e9 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 40adfed8b373c84a3e249e53218f9ccfc0142e18 Mon Sep 17 00:00:00 2001
From: Oli Scherer <github333195615777966@oli-obk.de>
Date: Thu, 12 Dec 2024 19:37:41 +0000
Subject: [PATCH 5/5] Remove now-obsolete visit_pattern_type_pattern

---
 compiler/rustc_ast_lowering/src/index.rs               |  4 ----
 compiler/rustc_hir/src/intravisit.rs                   |  7 +------
 .../src/collect/resolve_bound_vars.rs                  |  5 -----
 compiler/rustc_passes/src/hir_id_validator.rs          |  4 ----
 .../bad_const_generics_args_on_const_param.rs          |  1 +
 .../bad_const_generics_args_on_const_param.stderr      | 10 ++++++++--
 6 files changed, 10 insertions(+), 21 deletions(-)

diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index c92f149d24cae..3126eef19354f 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -393,10 +393,6 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
         });
     }
 
-    fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
-        self.visit_pat(p)
-    }
-
     fn visit_precise_capturing_arg(
         &mut self,
         arg: &'hir PreciseCapturingArg<'hir>,
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index ddee06b3ab63d..b46ee141256dc 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -364,11 +364,6 @@ pub trait Visitor<'v>: Sized {
     fn visit_ty(&mut self, t: &'v Ty<'v>) -> Self::Result {
         walk_ty(self, t)
     }
-    fn visit_pattern_type_pattern(&mut self, _p: &'v Pat<'v>) {
-        // Do nothing. Only a few visitors need to know the details of the pattern type,
-        // and they opt into it. All other visitors will just choke on our fake patterns
-        // because they aren't in a body.
-    }
     fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
         walk_generic_param(self, p)
     }
@@ -918,7 +913,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v>) -> V::Resul
         }
         TyKind::Pat(ty, pat) => {
             try_visit!(visitor.visit_ty(ty));
-            try_visit!(visitor.visit_pattern_type_pattern(pat));
+            try_visit!(visitor.visit_pat(pat));
         }
     }
     V::Result::output()
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 74f381d266116..d17026a17733b 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -826,11 +826,6 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip(self))]
-    fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::Pat<'tcx>) {
-        intravisit::walk_pat(self, p)
-    }
-
     #[instrument(level = "debug", skip(self))]
     fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem<'tcx>) {
         use self::hir::TraitItemKind::*;
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index f6b70d9389bb9..434837a17356f 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -161,8 +161,4 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
         let mut inner_visitor = self.new_visitor(self.tcx);
         inner_visitor.check(i.owner_id, |this| intravisit::walk_impl_item(this, i));
     }
-
-    fn visit_pattern_type_pattern(&mut self, p: &'hir hir::Pat<'hir>) {
-        self.visit_pat(p)
-    }
 }
diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs
index 55f45ade38804..18aec6d9d0adc 100644
--- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs
+++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs
@@ -6,5 +6,6 @@ type Pat<const START: u32, const END: u32> =
 //~^ ERROR type and const arguments are not allowed on const parameter `START`
 //~| ERROR type arguments are not allowed on const parameter `END`
 //~| ERROR associated item constraints are not allowed here
+//~| ERROR the placeholder `_` is not allowed within types on item signatures
 
 fn main() {}
diff --git a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr
index 7f4e6e314f534..9f37c057333b4 100644
--- a/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr
+++ b/tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr
@@ -32,7 +32,13 @@ error[E0229]: associated item constraints are not allowed here
 LL |     std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
    |                                                                   ^^^^^^^^^^ associated item constraint not allowed here
 
-error: aborting due to 3 previous errors
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for type aliases
+  --> $DIR/bad_const_generics_args_on_const_param.rs:5:64
+   |
+LL |     std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
+   |                                                                ^ not allowed in type signatures
+
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0109, E0229.
+Some errors have detailed explanations: E0109, E0121, E0229.
 For more information about an error, try `rustc --explain E0109`.