about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs81
-rw-r--r--compiler/rustc_driver_impl/src/pretty.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs21
-rw-r--r--compiler/rustc_hir/src/intravisit.rs18
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/collect/generics_of.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of.rs21
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/errors/pattern_types.rs7
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs65
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs51
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs2
-rw-r--r--compiler/rustc_passes/src/hir_id_validator.rs4
-rw-r--r--src/tools/clippy/clippy_utils/src/hir_utils.rs20
-rw-r--r--tests/ui/type/pattern_types/assoc_const.default.stderr36
-rw-r--r--tests/ui/type/pattern_types/assoc_const.rs24
-rw-r--r--tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs10
-rw-r--r--tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr42
-rw-r--r--tests/ui/type/pattern_types/bad_pat.rs2
-rw-r--r--tests/ui/type/pattern_types/bad_pat.stderr2
-rw-r--r--tests/ui/type/pattern_types/const_block.rs10
-rw-r--r--tests/ui/type/pattern_types/const_block.stderr72
-rw-r--r--tests/ui/type/pattern_types/free_const.rs13
-rw-r--r--tests/ui/type/pattern_types/nested.rs4
-rw-r--r--tests/ui/type/pattern_types/nested.stderr52
-rw-r--r--tests/ui/type/pattern_types/pattern_type_mismatch.rs12
-rw-r--r--tests/ui/type/pattern_types/pattern_type_mismatch.stderr44
-rw-r--r--tests/ui/type/pattern_types/unimplemented_pat.rs8
-rw-r--r--tests/ui/type/pattern_types/unimplemented_pat.stderr21
33 files changed, 474 insertions, 201 deletions
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index f8fb21d5cd0..d1e23bf2522 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -412,8 +412,12 @@ 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_pattern_type_pattern(&mut self, pat: &'hir hir::TyPat<'hir>) {
+        self.insert(pat.span, pat.hir_id, Node::TyPat(pat));
+
+        self.with_parent(pat.hir_id, |this| {
+            intravisit::walk_ty_pat(this, pat);
+        });
     }
 
     fn visit_precise_capturing_arg(
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 893da930855..8728af9997a 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -1377,7 +1377,9 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                     }
                 }
             }
-            TyKind::Pat(ty, pat) => hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_pat(pat)),
+            TyKind::Pat(ty, pat) => {
+                hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat))
+            }
             TyKind::MacCall(_) => {
                 span_bug!(t.span, "`TyKind::MacCall` should have been expanded by now")
             }
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index cde8ddbfe03..bb9b2a13185 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -4,10 +4,10 @@ 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_hir::def::{DefKind, Res};
 use rustc_middle::span_bug;
 use rustc_span::source_map::{Spanned, respan};
-use rustc_span::{Ident, Span};
+use rustc_span::{Ident, Span, kw};
 
 use super::errors::{
     ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
@@ -429,4 +429,81 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         };
         self.arena.alloc(hir::PatExpr { hir_id: self.lower_node_id(expr.id), span, kind })
     }
+
+    pub(crate) fn lower_ty_pat(&mut self, pattern: &Pat) -> &'hir hir::TyPat<'hir> {
+        self.arena.alloc(self.lower_ty_pat_mut(pattern))
+    }
+
+    fn lower_ty_pat_mut(&mut self, mut pattern: &Pat) -> hir::TyPat<'hir> {
+        // loop here to avoid recursion
+        let pat_hir_id = self.lower_node_id(pattern.id);
+        let node = loop {
+            match &pattern.kind {
+                PatKind::Range(e1, e2, Spanned { node: end, .. }) => {
+                    // FIXME(pattern_types): remove this closure and call `lower_const_arg` instead.
+                    // That requires first modifying the AST to have const args here.
+                    let mut lower_expr = |e: &Expr| -> &_ {
+                        if let ExprKind::Path(None, path) = &e.kind
+                            && let Some(res) = self
+                                .resolver
+                                .get_partial_res(e.id)
+                                .and_then(|partial_res| partial_res.full_res())
+                        {
+                            self.lower_const_path_to_const_arg(path, res, e.id, e.span)
+                        } else {
+                            let node_id = self.next_node_id();
+                            let def_id = self.create_def(
+                                self.current_hir_id_owner.def_id,
+                                node_id,
+                                kw::Empty,
+                                DefKind::AnonConst,
+                                e.span,
+                            );
+                            let hir_id = self.lower_node_id(node_id);
+                            let ac = self.arena.alloc(hir::AnonConst {
+                                def_id,
+                                hir_id,
+                                body: self.lower_const_body(pattern.span, Some(e)),
+                                span: self.lower_span(pattern.span),
+                            });
+                            self.arena.alloc(hir::ConstArg {
+                                hir_id: self.next_id(),
+                                kind: hir::ConstArgKind::Anon(ac),
+                            })
+                        }
+                    };
+                    break hir::TyPatKind::Range(
+                        e1.as_deref().map(|e| lower_expr(e)),
+                        e2.as_deref().map(|e| lower_expr(e)),
+                        self.lower_range_end(end, e2.is_some()),
+                    );
+                }
+                // return inner to be processed in next loop
+                PatKind::Paren(inner) => pattern = inner,
+                PatKind::MacCall(_) => panic!("{:?} shouldn't exist here", pattern.span),
+                PatKind::Err(guar) => break hir::TyPatKind::Err(*guar),
+                PatKind::Deref(..)
+                | PatKind::Box(..)
+                | PatKind::Or(..)
+                | PatKind::Struct(..)
+                | PatKind::TupleStruct(..)
+                | PatKind::Tuple(..)
+                | PatKind::Ref(..)
+                | PatKind::Expr(..)
+                | PatKind::Guard(..)
+                | PatKind::Slice(_)
+                | PatKind::Ident(..)
+                | PatKind::Path(..)
+                | PatKind::Wild
+                | PatKind::Never
+                | PatKind::Rest => {
+                    break hir::TyPatKind::Err(
+                        self.dcx().span_err(pattern.span, "pattern not supported in pattern types"),
+                    );
+                }
+            }
+        };
+
+        hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
+    }
 }
diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs
index 9ace486fa56..576b1c76823 100644
--- a/compiler/rustc_driver_impl/src/pretty.rs
+++ b/compiler/rustc_driver_impl/src/pretty.rs
@@ -101,6 +101,10 @@ impl<'tcx> pprust_hir::PpAnn for HirIdentifiedAnn<'tcx> {
                 s.s.space();
                 s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
             }
+            pprust_hir::AnnNode::TyPat(pat) => {
+                s.s.space();
+                s.synth_comment(format!("ty pat hir_id: {}", pat.hir_id));
+            }
             pprust_hir::AnnNode::Arm(arm) => {
                 s.s.space();
                 s.synth_comment(format!("arm hir_id: {}", arm.hir_id));
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 5483b97a7f4..4631432038b 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1419,6 +1419,14 @@ impl<'hir> Block<'hir> {
 }
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub struct TyPat<'hir> {
+    #[stable_hasher(ignore)]
+    pub hir_id: HirId,
+    pub kind: TyPatKind<'hir>,
+    pub span: Span,
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub struct Pat<'hir> {
     #[stable_hasher(ignore)]
     pub hir_id: HirId,
@@ -1592,6 +1600,15 @@ pub enum PatExprKind<'hir> {
 }
 
 #[derive(Debug, Clone, Copy, HashStable_Generic)]
+pub enum TyPatKind<'hir> {
+    /// A range pattern (e.g., `1..=2` or `1..2`).
+    Range(Option<&'hir ConstArg<'hir>>, Option<&'hir ConstArg<'hir>>, RangeEnd),
+
+    /// A placeholder for a pattern that wasn't well formed in some way.
+    Err(ErrorGuaranteed),
+}
+
+#[derive(Debug, Clone, Copy, HashStable_Generic)]
 pub enum PatKind<'hir> {
     /// Represents a wildcard pattern (i.e., `_`).
     Wild,
@@ -3384,7 +3401,7 @@ pub enum TyKind<'hir, Unambig = ()> {
     /// Placeholder for a type that has failed to be defined.
     Err(rustc_span::ErrorGuaranteed),
     /// Pattern types (`pattern_type!(u32 is 1..)`)
-    Pat(&'hir Ty<'hir>, &'hir Pat<'hir>),
+    Pat(&'hir Ty<'hir>, &'hir TyPat<'hir>),
     /// `TyKind::Infer` means the type should be inferred instead of it having been
     /// specified. This can appear anywhere in a type.
     ///
@@ -4370,6 +4387,7 @@ pub enum Node<'hir> {
     AssocItemConstraint(&'hir AssocItemConstraint<'hir>),
     TraitRef(&'hir TraitRef<'hir>),
     OpaqueTy(&'hir OpaqueTy<'hir>),
+    TyPat(&'hir TyPat<'hir>),
     Pat(&'hir Pat<'hir>),
     PatField(&'hir PatField<'hir>),
     /// Needed as its own node with its own HirId for tracking
@@ -4432,6 +4450,7 @@ impl<'hir> Node<'hir> {
             | Node::Block(..)
             | Node::Ctor(..)
             | Node::Pat(..)
+            | Node::TyPat(..)
             | Node::PatExpr(..)
             | Node::Arm(..)
             | Node::LetStmt(..)
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 31764ab1209..6519552d604 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -393,10 +393,8 @@ pub trait Visitor<'v>: Sized {
     fn visit_expr_field(&mut self, field: &'v ExprField<'v>) -> Self::Result {
         walk_expr_field(self, field)
     }
-    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_pattern_type_pattern(&mut self, p: &'v TyPat<'v>) -> Self::Result {
+        walk_ty_pat(self, p)
     }
     fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) -> Self::Result {
         walk_generic_param(self, p)
@@ -702,6 +700,18 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Res
     visitor.visit_expr(arm.body)
 }
 
+pub fn walk_ty_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v TyPat<'v>) -> V::Result {
+    try_visit!(visitor.visit_id(pattern.hir_id));
+    match pattern.kind {
+        TyPatKind::Range(lower_bound, upper_bound, _) => {
+            visit_opt!(visitor, visit_const_arg_unambig, lower_bound);
+            visit_opt!(visitor, visit_const_arg_unambig, upper_bound);
+        }
+        TyPatKind::Err(_) => (),
+    }
+    V::Result::output()
+}
+
 pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat<'v>) -> V::Result {
     try_visit!(visitor.visit_id(pattern.hir_id));
     match pattern.kind {
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index a4b5a87361e..c28c1afcfe6 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -436,9 +436,6 @@ hir_analysis_paren_sugar_attribute = the `#[rustc_paren_sugar]` attribute is a t
 hir_analysis_parenthesized_fn_trait_expansion =
     parenthesized trait syntax expands to `{$expanded_type}`
 
-hir_analysis_pattern_type_non_const_range = range patterns must have constant range start and end
-hir_analysis_pattern_type_wild_pat = wildcard patterns are not permitted for pattern types
-    .label = this type is the same as the inner type without a pattern
 hir_analysis_placeholder_not_allowed_item_signatures = the placeholder `_` is not allowed within types on item signatures for {$kind}
     .label = not allowed in type signatures
 hir_analysis_precise_capture_self_alias = `Self` can't be captured in `use<...>` precise captures list, since it is an alias
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index 2ac8acbd3a4..c0902398a54 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -198,6 +198,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
                     {
                         Some(parent_did)
                     }
+                    Node::TyPat(_) => Some(parent_did),
                     _ => None,
                 }
             }
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 d67b9d33596..76006354717 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -831,8 +831,8 @@ 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)
+    fn visit_pattern_type_pattern(&mut self, p: &'tcx hir::TyPat<'tcx>) {
+        intravisit::walk_ty_pat(self, p)
     }
 
     #[instrument(level = "debug", skip(self))]
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs
index 348d4d708b5..4e12db190fd 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs
@@ -18,9 +18,10 @@ use crate::hir_ty_lowering::HirTyLowerer;
 
 mod opaque;
 
-fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
+fn anon_const_type_of<'tcx>(icx: &ItemCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     use hir::*;
     use rustc_middle::ty::Ty;
+    let tcx = icx.tcx;
     let hir_id = tcx.local_def_id_to_hir_id(def_id);
 
     let node = tcx.hir_node(hir_id);
@@ -54,7 +55,7 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
             hir_id: arg_hir_id,
             kind: ConstArgKind::Anon(&AnonConst { hir_id: anon_hir_id, .. }),
             ..
-        }) if anon_hir_id == hir_id => const_arg_anon_type_of(tcx, arg_hir_id, span),
+        }) if anon_hir_id == hir_id => const_arg_anon_type_of(icx, arg_hir_id, span),
 
         // Anon consts outside the type system.
         Node::Expr(&Expr { kind: ExprKind::InlineAsm(asm), .. })
@@ -138,10 +139,12 @@ fn anon_const_type_of<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Ty<'tcx> {
     }
 }
 
-fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
+fn const_arg_anon_type_of<'tcx>(icx: &ItemCtxt<'tcx>, arg_hir_id: HirId, span: Span) -> Ty<'tcx> {
     use hir::*;
     use rustc_middle::ty::Ty;
 
+    let tcx = icx.tcx;
+
     match tcx.parent_hir_node(arg_hir_id) {
         // Array length const arguments do not have `type_of` fed as there is never a corresponding
         // generic parameter definition.
@@ -149,7 +152,15 @@ fn const_arg_anon_type_of<'tcx>(tcx: TyCtxt<'tcx>, arg_hir_id: HirId, span: Span
         | Node::Expr(&Expr { kind: ExprKind::Repeat(_, ref constant), .. })
             if constant.hir_id == arg_hir_id =>
         {
-            return tcx.types.usize;
+            tcx.types.usize
+        }
+
+        Node::TyPat(pat) => {
+            let hir::TyKind::Pat(ty, p) = tcx.parent_hir_node(pat.hir_id).expect_ty().kind else {
+                bug!()
+            };
+            assert_eq!(p.hir_id, pat.hir_id);
+            icx.lower_ty(ty)
         }
 
         // This is not a `bug!` as const arguments in path segments that did not resolve to anything
@@ -344,7 +355,7 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_
             tcx.typeck(def_id).node_type(hir_id)
         }
 
-        Node::AnonConst(_) => anon_const_type_of(tcx, def_id),
+        Node::AnonConst(_) => anon_const_type_of(&icx, def_id),
 
         Node::ConstBlock(_) => {
             let args = ty::GenericArgs::identity_for_item(tcx, def_id.to_def_id());
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 1dcea5d0335..9769be30226 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1605,13 +1605,6 @@ pub(crate) struct OpaqueCapturesHigherRankedLifetime {
     pub bad_place: &'static str,
 }
 
-#[derive(Diagnostic)]
-#[diag(hir_analysis_pattern_type_non_const_range)]
-pub(crate) struct NonConstRange {
-    #[primary_span]
-    pub span: Span,
-}
-
 #[derive(Subdiagnostic)]
 pub(crate) enum InvalidReceiverTyHint {
     #[note(hir_analysis_invalid_receiver_ty_help_weak_note)]
diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs
index 272edbe841b..ec7b3aaa1c1 100644
--- a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs
+++ b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs
@@ -3,13 +3,6 @@ use rustc_middle::ty::Ty;
 use rustc_span::Span;
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_pattern_type_wild_pat)]
-pub(crate) struct WildPatTy {
-    #[primary_span]
-    pub span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_analysis_invalid_base_type)]
 pub(crate) struct InvalidBaseType<'tcx> {
     pub ty: Ty<'tcx>,
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 5813fdeae76..079e8921627 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -53,7 +53,7 @@ use tracing::{debug, instrument};
 
 use crate::bounds::Bounds;
 use crate::check::check_abi_fn_ptr;
-use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, WildPatTy};
+use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType};
 use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
 use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args};
 use crate::middle::resolve_bound_vars as rbv;
@@ -2435,11 +2435,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let ty_span = ty.span;
                 let ty = self.lower_ty(ty);
                 let pat_ty = match pat.kind {
-                    hir::PatKind::Wild => {
-                        let err = self.dcx().emit_err(WildPatTy { span: pat.span });
-                        Ty::new_error(tcx, err)
-                    }
-                    hir::PatKind::Range(start, end, include_end) => {
+                    hir::TyPatKind::Range(start, end, include_end) => {
                         let ty = match ty.kind() {
                             ty::Int(_) | ty::Uint(_) | ty::Char => ty,
                             _ => Ty::new_error(
@@ -2452,54 +2448,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                                 }),
                             ),
                         };
-                        let expr_to_const = |expr: &'tcx hir::PatExpr<'tcx>| -> ty::Const<'tcx> {
-                            let (c, c_ty) = match expr.kind {
-                                hir::PatExprKind::Lit { lit, negated } => {
-                                    let lit_input =
-                                        LitToConstInput { lit: &lit.node, ty, neg: negated };
-                                    let ct = tcx.lit_to_const(lit_input);
-                                    (ct, ty)
-                                }
-
-                                hir::PatExprKind::Path(hir::QPath::Resolved(
-                                    _,
-                                    path @ &hir::Path {
-                                        res: Res::Def(DefKind::ConstParam, def_id),
-                                        ..
-                                    },
-                                )) => {
-                                    match self.prohibit_generic_args(
-                                        path.segments.iter(),
-                                        GenericsArgsErrExtend::Param(def_id),
-                                    ) {
-                                        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),
-                                        ),
-                                    }
-                                }
-
-                                _ => {
-                                    let err = tcx
-                                        .dcx()
-                                        .emit_err(crate::errors::NonConstRange { span: expr.span });
-                                    (ty::Const::new_error(tcx, err), Ty::new_error(tcx, err))
-                                }
-                            };
-                            self.record_ty(expr.hir_id, c_ty, expr.span);
-                            c
-                        };
-
-                        let start = start.map(expr_to_const);
-                        let end = end.map(expr_to_const);
+                        let start = start.map(|expr| self.lower_const_arg(expr, FeedConstTy::No));
+                        let end = end.map(|expr| self.lower_const_arg(expr, FeedConstTy::No));
 
                         let include_end = match include_end {
                             hir::RangeEnd::Included => true,
@@ -2509,12 +2459,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
                         Ty::new_pat(tcx, ty, pat)
                     }
-                    hir::PatKind::Err(e) => Ty::new_error(tcx, e),
-                    _ => Ty::new_error_with_message(
-                        tcx,
-                        pat.span,
-                        format!("unsupported pattern for pattern type: {pat:#?}"),
-                    ),
+                    hir::TyPatKind::Err(e) => Ty::new_error(tcx, e),
                 };
                 self.record_ty(pat.hir_id, ty, pat.span);
                 pat_ty
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index a91afa51230..3b163d0bc20 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -18,7 +18,7 @@ use rustc_ast_pretty::pprust::state::MacHeader;
 use rustc_ast_pretty::pprust::{Comments, PrintState};
 use rustc_hir::{
     BindingMode, ByRef, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind,
-    HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term,
+    HirId, LifetimeParamKind, Node, PatKind, PreciseCapturingArg, RangeEnd, Term, TyPatKind,
 };
 use rustc_span::source_map::SourceMap;
 use rustc_span::{FileName, Ident, Span, Symbol, kw};
@@ -35,6 +35,7 @@ pub enum AnnNode<'a> {
     SubItem(HirId),
     Expr(&'a hir::Expr<'a>),
     Pat(&'a hir::Pat<'a>),
+    TyPat(&'a hir::TyPat<'a>),
     Arm(&'a hir::Arm<'a>),
 }
 
@@ -198,6 +199,7 @@ impl<'a> State<'a> {
             Node::TraitRef(a) => self.print_trait_ref(a),
             Node::OpaqueTy(o) => self.print_opaque_ty(o),
             Node::Pat(a) => self.print_pat(a),
+            Node::TyPat(a) => self.print_ty_pat(a),
             Node::PatField(a) => self.print_patfield(a),
             Node::PatExpr(a) => self.print_pat_expr(a),
             Node::Arm(a) => self.print_arm(a),
@@ -224,6 +226,16 @@ impl<'a> State<'a> {
             Node::Err(_) => self.word("/*ERROR*/"),
         }
     }
+
+    fn print_generic_arg(&mut self, generic_arg: &GenericArg<'_>, elide_lifetimes: bool) {
+        match generic_arg {
+            GenericArg::Lifetime(lt) if !elide_lifetimes => self.print_lifetime(lt),
+            GenericArg::Lifetime(_) => {}
+            GenericArg::Type(ty) => self.print_type(ty.as_unambig_ty()),
+            GenericArg::Const(ct) => self.print_const_arg(ct.as_unambig_ct()),
+            GenericArg::Infer(_inf) => self.word("_"),
+        }
+    }
 }
 
 impl std::ops::Deref for State<'_> {
@@ -448,7 +460,7 @@ impl<'a> State<'a> {
             hir::TyKind::Pat(ty, pat) => {
                 self.print_type(ty);
                 self.word(" is ");
-                self.print_pat(pat);
+                self.print_ty_pat(pat);
             }
         }
         self.end()
@@ -1797,13 +1809,7 @@ impl<'a> State<'a> {
                 if nonelided_generic_args {
                     start_or_comma(self);
                     self.commasep(Inconsistent, generic_args.args, |s, generic_arg| {
-                        match generic_arg {
-                            GenericArg::Lifetime(lt) if !elide_lifetimes => s.print_lifetime(lt),
-                            GenericArg::Lifetime(_) => {}
-                            GenericArg::Type(ty) => s.print_type(ty.as_unambig_ty()),
-                            GenericArg::Const(ct) => s.print_const_arg(ct.as_unambig_ct()),
-                            GenericArg::Infer(_inf) => s.word("_"),
-                        }
+                        s.print_generic_arg(generic_arg, elide_lifetimes)
                     });
                 }
 
@@ -1864,6 +1870,33 @@ impl<'a> State<'a> {
         }
     }
 
+    fn print_ty_pat(&mut self, pat: &hir::TyPat<'_>) {
+        self.maybe_print_comment(pat.span.lo());
+        self.ann.pre(self, AnnNode::TyPat(pat));
+        // Pat isn't normalized, but the beauty of it
+        // is that it doesn't matter
+        match pat.kind {
+            TyPatKind::Range(begin, end, end_kind) => {
+                if let Some(expr) = begin {
+                    self.print_const_arg(expr);
+                }
+                match end_kind {
+                    RangeEnd::Included => self.word("..."),
+                    RangeEnd::Excluded => self.word(".."),
+                }
+                if let Some(expr) = end {
+                    self.print_const_arg(expr);
+                }
+            }
+            TyPatKind::Err(_) => {
+                self.popen();
+                self.word("/*ERROR*/");
+                self.pclose();
+            }
+        }
+        self.ann.post(self, AnnNode::TyPat(pat))
+    }
+
     fn print_pat(&mut self, pat: &hir::Pat<'_>) {
         self.maybe_print_comment(pat.span.lo());
         self.ann.pre(self, AnnNode::Pat(pat));
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index a519e177fbc..838cd1e03f9 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -412,7 +412,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             })
             | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. }) => true,
 
-            hir::Node::Pat(_) => {
+            hir::Node::TyPat(_) | hir::Node::Pat(_) => {
                 self.dcx().span_delayed_bug(expr.span, "place expr not allowed in pattern");
                 true
             }
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 926760b84aa..4df4624971d 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -937,6 +937,7 @@ impl<'hir> Map<'hir> {
             Node::TraitRef(tr) => tr.path.span,
             Node::OpaqueTy(op) => op.span,
             Node::Pat(pat) => pat.span,
+            Node::TyPat(pat) => pat.span,
             Node::PatField(field) => field.span,
             Node::PatExpr(lit) => lit.span,
             Node::Arm(arm) => arm.span,
@@ -1212,6 +1213,7 @@ fn hir_id_to_string(map: Map<'_>, id: HirId) -> String {
         Node::TraitRef(_) => node_str("trait ref"),
         Node::OpaqueTy(_) => node_str("opaque type"),
         Node::Pat(_) => node_str("pat"),
+        Node::TyPat(_) => node_str("pat ty"),
         Node::PatField(_) => node_str("pattern field"),
         Node::PatExpr(_) => node_str("pattern literal"),
         Node::Param(_) => node_str("param"),
diff --git a/compiler/rustc_passes/src/hir_id_validator.rs b/compiler/rustc_passes/src/hir_id_validator.rs
index f6b70d9389b..74038b24dcc 100644
--- a/compiler/rustc_passes/src/hir_id_validator.rs
+++ b/compiler/rustc_passes/src/hir_id_validator.rs
@@ -162,7 +162,7 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
         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)
+    fn visit_pattern_type_pattern(&mut self, p: &'hir hir::TyPat<'hir>) {
+        intravisit::walk_ty_pat(self, p)
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs
index d0eb5318e64..4bbf28115a6 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, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PrimTy, QPath, Stmt, StmtKind, StructTailExpr,
-    TraitBoundModifiers, Ty, TyKind,
+    TraitBoundModifiers, Ty, TyKind, TyPat, TyPatKind,
 };
 use rustc_lexer::{TokenKind, tokenize};
 use rustc_lint::LateContext;
@@ -1102,6 +1102,22 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
         }
     }
 
+    pub fn hash_ty_pat(&mut self, pat: &TyPat<'_>) {
+        std::mem::discriminant(&pat.kind).hash(&mut self.s);
+        match pat.kind {
+            TyPatKind::Range(s, e, i) => {
+                if let Some(s) = s {
+                    self.hash_const_arg(s);
+                }
+                if let Some(e) = e {
+                    self.hash_const_arg(e);
+                }
+                std::mem::discriminant(&i).hash(&mut self.s);
+            },
+            TyPatKind::Err(_) => {},
+        }
+    }
+
     pub fn hash_pat(&mut self, pat: &Pat<'_>) {
         std::mem::discriminant(&pat.kind).hash(&mut self.s);
         match pat.kind {
@@ -1247,7 +1263,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> {
             },
             TyKind::Pat(ty, pat) => {
                 self.hash_ty(ty);
-                self.hash_pat(pat);
+                self.hash_ty_pat(pat);
             },
             TyKind::Ptr(mut_ty) => {
                 self.hash_ty(mut_ty.ty);
diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr
new file mode 100644
index 00000000000..abda40e4681
--- /dev/null
+++ b/tests/ui/type/pattern_types/assoc_const.default.stderr
@@ -0,0 +1,36 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/assoc_const.rs:17:19
+   |
+LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/assoc_const.rs:17:19
+   |
+LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: constant expression depends on a generic parameter
+  --> $DIR/assoc_const.rs:20:19
+   |
+LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/assoc_const.rs:20:19
+   |
+LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/type/pattern_types/assoc_const.rs b/tests/ui/type/pattern_types/assoc_const.rs
new file mode 100644
index 00000000000..af0f7e4cbf3
--- /dev/null
+++ b/tests/ui/type/pattern_types/assoc_const.rs
@@ -0,0 +1,24 @@
+#![feature(pattern_types)]
+#![feature(pattern_type_macro)]
+#![cfg_attr(const_arg, feature(generic_const_exprs))]
+#![expect(incomplete_features)]
+
+//@ revisions: default const_arg
+
+//@[const_arg] check-pass
+
+use std::pat::pattern_type;
+
+trait Foo {
+    const START: u32;
+    const END: u32;
+}
+
+fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
+//[default]~^ ERROR: constant expression depends on a generic parameter
+//[default]~| ERROR: constant expression depends on a generic parameter
+fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
+//[default]~^ ERROR: constant expression depends on a generic parameter
+//[default]~| ERROR: constant expression depends on a generic parameter
+
+fn main() {}
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 c5f8b2764ec..0f10bf8ce62 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
@@ -1,10 +1,14 @@
+//@known-bug: #127972
+//@ failure-status: 101
+//@ normalize-stderr: "note: .*\n\n" -> ""
+//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> ""
+//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
+//@ rustc-env:RUST_BACKTRACE=0
+
 #![feature(pattern_types, pattern_type_macro)]
 #![allow(internal_features)]
 
 type Pat<const START: u32, const END: u32> =
     std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
-//~^ ERROR type and const arguments are not allowed on const parameter `START`
-//~| ERROR generic arguments are not allowed on const parameter `END`
-//~| ERROR associated item constraints are not allowed here
 
 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 f31809bf397..fbe80a19863 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
@@ -1,38 +1,14 @@
-error[E0109]: type and const arguments are not allowed on const parameter `START`
-  --> $DIR/bad_const_generics_args_on_const_param.rs:5:44
+error: internal compiler error: compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs:LL:CC: try_lower_anon_const_lit: received const param which shouldn't be possible
+  --> $DIR/bad_const_generics_args_on_const_param.rs:12:36
    |
 LL |     std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
-   |                                    -----   ^^  ^^^  ^ type and const arguments not allowed
-   |                                    |
-   |                                    not allowed on const parameter `START`
-   |
-note: const parameter `START` defined here
-  --> $DIR/bad_const_generics_args_on_const_param.rs:4:16
-   |
-LL | type Pat<const START: u32, const END: u32> =
-   |                ^^^^^
+   |                                    ^^^^^^^^^^^^^^^^^^^
 
-error[E0109]: generic arguments are not allowed on const parameter `END`
-  --> $DIR/bad_const_generics_args_on_const_param.rs:5:64
-   |
-LL |     std::pat::pattern_type!(u32 is START::<(), i32, 2>..=END::<_, Assoc = ()>);
-   |                                                          ---   ^ generic argument not allowed
-   |                                                          |
-   |                                                          not allowed on const parameter `END`
-   |
-note: const parameter `END` defined here
-  --> $DIR/bad_const_generics_args_on_const_param.rs:4:34
-   |
-LL | type Pat<const START: u32, const END: u32> =
-   |                                  ^^^
-
-error[E0229]: associated item constraints are not allowed here
-  --> $DIR/bad_const_generics_args_on_const_param.rs:5:67
-   |
-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
+Box<dyn Any>
+query stack during panic:
+#0 [type_of] expanding type alias `Pat`
+#1 [check_well_formed] checking that `Pat` is well-formed
+... and 2 other queries... use `env RUST_BACKTRACE=1` to see the full query stack
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0109, E0229.
-For more information about an error, try `rustc --explain E0109`.
diff --git a/tests/ui/type/pattern_types/bad_pat.rs b/tests/ui/type/pattern_types/bad_pat.rs
index 6cb2a0f1f8e..549b0d11dd1 100644
--- a/tests/ui/type/pattern_types/bad_pat.rs
+++ b/tests/ui/type/pattern_types/bad_pat.rs
@@ -8,6 +8,6 @@ type NonNullU32_2 = pattern_type!(u32 is 1..=);
 type Positive2 = pattern_type!(i32 is 0..=);
 //~^ ERROR: inclusive range with no end
 type Wild = pattern_type!(() is _);
-//~^ ERROR: wildcard patterns are not permitted for pattern types
+//~^ ERROR: pattern not supported in pattern types
 
 fn main() {}
diff --git a/tests/ui/type/pattern_types/bad_pat.stderr b/tests/ui/type/pattern_types/bad_pat.stderr
index c857cc3c3ad..d2a5a20bf89 100644
--- a/tests/ui/type/pattern_types/bad_pat.stderr
+++ b/tests/ui/type/pattern_types/bad_pat.stderr
@@ -24,7 +24,7 @@ LL - type Positive2 = pattern_type!(i32 is 0..=);
 LL + type Positive2 = pattern_type!(i32 is 0..);
    |
 
-error: wildcard patterns are not permitted for pattern types
+error: pattern not supported in pattern types
   --> $DIR/bad_pat.rs:10:33
    |
 LL | type Wild = pattern_type!(() is _);
diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs
new file mode 100644
index 00000000000..49c87f4fa0d
--- /dev/null
+++ b/tests/ui/type/pattern_types/const_block.rs
@@ -0,0 +1,10 @@
+#![feature(pattern_types)]
+#![feature(pattern_type_macro)]
+#![feature(inline_const_pat)]
+
+use std::pat::pattern_type;
+
+fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+//~^ ERROR: cycle
+
+fn main() {}
diff --git a/tests/ui/type/pattern_types/const_block.stderr b/tests/ui/type/pattern_types/const_block.stderr
new file mode 100644
index 00000000000..82b616105af
--- /dev/null
+++ b/tests/ui/type/pattern_types/const_block.stderr
@@ -0,0 +1,72 @@
+error[E0391]: cycle detected when evaluating type-level constant
+  --> $DIR/const_block.rs:7:36
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                    ^^^^^^^^^^^^^^
+   |
+note: ...which requires const-evaluating + checking `bar::{constant#2}`...
+  --> $DIR/const_block.rs:7:36
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                    ^^^^^^^^^^^^^^
+note: ...which requires caching mir of `bar::{constant#2}` for CTFE...
+  --> $DIR/const_block.rs:7:36
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                    ^^^^^^^^^^^^^^
+note: ...which requires elaborating drops for `bar::{constant#2}`...
+  --> $DIR/const_block.rs:7:36
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                    ^^^^^^^^^^^^^^
+note: ...which requires borrow-checking `bar::{constant#2}`...
+  --> $DIR/const_block.rs:7:36
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                    ^^^^^^^^^^^^^^
+note: ...which requires borrow-checking `bar::{constant#0}`...
+  --> $DIR/const_block.rs:7:41
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                         ^^^^^^^^^
+note: ...which requires promoting constants in MIR for `bar::{constant#0}`...
+  --> $DIR/const_block.rs:7:41
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                         ^^^^^^^^^
+note: ...which requires const checking `bar::{constant#0}`...
+  --> $DIR/const_block.rs:7:41
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                         ^^^^^^^^^
+note: ...which requires building MIR for `bar::{constant#0}`...
+  --> $DIR/const_block.rs:7:41
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                         ^^^^^^^^^
+note: ...which requires match-checking `bar::{constant#0}`...
+  --> $DIR/const_block.rs:7:41
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                         ^^^^^^^^^
+note: ...which requires type-checking `bar::{constant#0}`...
+  --> $DIR/const_block.rs:7:41
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   |                                         ^^^^^^^^^
+note: ...which requires type-checking `bar`...
+  --> $DIR/const_block.rs:7:1
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...which again requires evaluating type-level constant, completing the cycle
+note: cycle used when checking that `bar` is well-formed
+  --> $DIR/const_block.rs:7:1
+   |
+LL | fn bar(x: pattern_type!(u32 is 0..=const{ 5 + 5 })) {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0391`.
diff --git a/tests/ui/type/pattern_types/free_const.rs b/tests/ui/type/pattern_types/free_const.rs
new file mode 100644
index 00000000000..2e29fce2379
--- /dev/null
+++ b/tests/ui/type/pattern_types/free_const.rs
@@ -0,0 +1,13 @@
+//@ check-pass
+
+#![feature(pattern_types)]
+#![feature(pattern_type_macro)]
+
+use std::pat::pattern_type;
+
+const START: u32 = 0;
+const END: u32 = 10;
+
+fn foo(_: pattern_type!(u32 is START..=END)) {}
+
+fn main() {}
diff --git a/tests/ui/type/pattern_types/nested.rs b/tests/ui/type/pattern_types/nested.rs
index 519fb3f05b4..9ca9c7923de 100644
--- a/tests/ui/type/pattern_types/nested.rs
+++ b/tests/ui/type/pattern_types/nested.rs
@@ -9,16 +9,20 @@ use std::pat::pattern_type;
 // or still validate correctly.
 const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
 //~^ ERROR: not a valid base type for range patterns
+//~| ERROR: mismatched types
 
 // We want to get the most narrowest version that a pattern could be
 const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
 //~^ ERROR: not a valid base type for range patterns
+//~| ERROR: mismatched types
 
 const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
 //~^ ERROR: not a valid base type for range patterns
+//~| ERROR: mismatched types
 
 const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
 //~^ ERROR: not a valid base type for range patterns
+//~| ERROR: mismatched types
 
 const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
 //~^ ERROR: not a valid base type for range patterns
diff --git a/tests/ui/type/pattern_types/nested.stderr b/tests/ui/type/pattern_types/nested.stderr
index 99d3979e98c..b753b0a9c9b 100644
--- a/tests/ui/type/pattern_types/nested.stderr
+++ b/tests/ui/type/pattern_types/nested.stderr
@@ -11,52 +11,86 @@ LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!(
    |                                                               ^^^
 
 error: `(i32) is 1..=` is not a valid base type for range patterns
-  --> $DIR/nested.rs:14:35
+  --> $DIR/nested.rs:15:35
    |
 LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: range patterns only support integers
-  --> $DIR/nested.rs:14:64
+  --> $DIR/nested.rs:15:64
    |
 LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
    |                                                                ^^^^^
 
 error: `(i32) is 1..=` is not a valid base type for range patterns
-  --> $DIR/nested.rs:17:35
+  --> $DIR/nested.rs:19:35
    |
 LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
    |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: range patterns only support integers
-  --> $DIR/nested.rs:17:64
+  --> $DIR/nested.rs:19:64
    |
 LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
    |                                                                ^^^
 
 error: `()` is not a valid base type for range patterns
-  --> $DIR/nested.rs:20:35
+  --> $DIR/nested.rs:23:35
    |
 LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
    |                                   ^^
    |
 note: range patterns only support integers
-  --> $DIR/nested.rs:20:41
+  --> $DIR/nested.rs:23:41
    |
 LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
    |                                         ^^^
 
 error: `f32` is not a valid base type for range patterns
-  --> $DIR/nested.rs:23:35
+  --> $DIR/nested.rs:27:35
    |
 LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
    |                                   ^^^
    |
 note: range patterns only support integers
-  --> $DIR/nested.rs:23:42
+  --> $DIR/nested.rs:27:42
    |
 LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
    |                                          ^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error[E0308]: mismatched types
+  --> $DIR/nested.rs:10:63
+   |
+LL | const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
+   |                                                               ^ expected `(u32) is 1..=`, found integer
+   |
+   = note: expected pattern type `(u32) is 1..=`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/nested.rs:15:67
+   |
+LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
+   |                                                                   ^^ expected `(i32) is 1..=`, found integer
+   |
+   = note: expected pattern type `(i32) is 1..=`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/nested.rs:19:66
+   |
+LL | const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
+   |                                                                  ^ expected `(i32) is 1..=`, found integer
+   |
+   = note: expected pattern type `(i32) is 1..=`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/nested.rs:23:43
+   |
+LL | const BAD_NESTING4: pattern_type!(() is ..0) = todo!();
+   |                                           ^ expected `()`, found integer
+
+error: aborting due to 9 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type/pattern_types/pattern_type_mismatch.rs b/tests/ui/type/pattern_types/pattern_type_mismatch.rs
index 8d375d7932b..0c88f27d836 100644
--- a/tests/ui/type/pattern_types/pattern_type_mismatch.rs
+++ b/tests/ui/type/pattern_types/pattern_type_mismatch.rs
@@ -1,20 +1,16 @@
 //! Check that pattern types patterns must be of the type of the base type
 
-//@ known-bug: unknown
-//@ failure-status: 101
-//@ normalize-stderr: "note: .*\n\n" -> ""
-//@ normalize-stderr: "thread 'rustc' panicked.*\n" -> ""
-//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
-//@ normalize-stderr: "(delayed at compiler/rustc_mir_transform/src/lib.rs:)\d+:\d+" -> "$1:LL:CC"
-//@ rustc-env:RUST_BACKTRACE=0
-
 #![feature(pattern_types)]
 #![feature(pattern_type_macro)]
 
 use std::pat::pattern_type;
 
 const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
+//~^ ERROR: mismatched types
+//~| ERROR: mismatched types
 
 const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
+//~^ ERROR: mismatched types
+//~| ERROR: mismatched types
 
 fn main() {}
diff --git a/tests/ui/type/pattern_types/pattern_type_mismatch.stderr b/tests/ui/type/pattern_types/pattern_type_mismatch.stderr
index ee413133ab3..19b0c1059c8 100644
--- a/tests/ui/type/pattern_types/pattern_type_mismatch.stderr
+++ b/tests/ui/type/pattern_types/pattern_type_mismatch.stderr
@@ -1,31 +1,37 @@
-error: internal compiler error: ty::ConstKind::Error constructed but no error reported
+error[E0308]: mismatched types
+  --> $DIR/pattern_type_mismatch.rs:8:41
    |
-   = error: internal compiler error: ty::ConstKind::Error constructed but no error reported
+LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
+   |                                         ^^^ expected `u8`, found `char`
+   |
+help: if you meant to write a byte literal, prefix with `b`
    |
-   = note: delayed at compiler/rustc_mir_build/src/thir/constant.rs:72:21 - disabled backtrace
-   = error: internal compiler error: mir_const_qualif: MIR had errors
-  --> $DIR/pattern_type_mismatch.rs:16:1
+LL | const BAD_NESTING4: pattern_type!(u8 is b'a'..='a') = todo!();
+   |                                         ~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/pattern_type_mismatch.rs:8:47
    |
 LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                               ^^^ expected `u8`, found `char`
    |
-note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace
-  --> $DIR/pattern_type_mismatch.rs:16:1
+help: if you meant to write a byte literal, prefix with `b`
    |
-LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..='a') = todo!();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | const BAD_NESTING4: pattern_type!(u8 is 'a'..=b'a') = todo!();
+   |                                               ~~~~
 
-error: internal compiler error: mir_const_qualif: MIR had errors
-  --> $DIR/pattern_type_mismatch.rs:18:1
+error[E0308]: mismatched types
+  --> $DIR/pattern_type_mismatch.rs:12:43
    |
 LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: delayed at compiler/rustc_mir_transform/src/lib.rs::LL:CC - disabled backtrace
-  --> $DIR/pattern_type_mismatch.rs:18:1
+   |                                           ^ expected `char`, found `u8`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern_type_mismatch.rs:12:47
    |
 LL | const BAD_NESTING5: pattern_type!(char is 1..=1) = todo!();
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                               ^ expected `char`, found `u8`
+
+error: aborting due to 4 previous errors
 
-query stack during panic:
-end of query stack
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type/pattern_types/unimplemented_pat.rs b/tests/ui/type/pattern_types/unimplemented_pat.rs
index b2398cec7c9..44851ec1a10 100644
--- a/tests/ui/type/pattern_types/unimplemented_pat.rs
+++ b/tests/ui/type/pattern_types/unimplemented_pat.rs
@@ -1,14 +1,14 @@
 //! This test ensures we do not ICE for unimplemented
-//! patterns unless the feature gate is enabled.
+//! patterns even if the feature gate is enabled.
 
-#![feature(pattern_type_macro)]
+#![feature(pattern_type_macro, pattern_types)]
 
 use std::pat::pattern_type;
 
 type Always = pattern_type!(Option<u32> is Some(_));
-//~^ ERROR: pattern types are unstable
+//~^ ERROR: pattern not supported
 
 type Binding = pattern_type!(Option<u32> is x);
-//~^ ERROR: pattern types are unstable
+//~^ ERROR: pattern not supported
 
 fn main() {}
diff --git a/tests/ui/type/pattern_types/unimplemented_pat.stderr b/tests/ui/type/pattern_types/unimplemented_pat.stderr
index 7b0f9cbaa6a..a1e55ed02c4 100644
--- a/tests/ui/type/pattern_types/unimplemented_pat.stderr
+++ b/tests/ui/type/pattern_types/unimplemented_pat.stderr
@@ -1,23 +1,14 @@
-error[E0658]: pattern types are unstable
-  --> $DIR/unimplemented_pat.rs:8:15
+error: pattern not supported in pattern types
+  --> $DIR/unimplemented_pat.rs:8:44
    |
 LL | type Always = pattern_type!(Option<u32> is Some(_));
-   |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
-   = help: add `#![feature(pattern_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   |                                            ^^^^^^^
 
-error[E0658]: pattern types are unstable
-  --> $DIR/unimplemented_pat.rs:11:16
+error: pattern not supported in pattern types
+  --> $DIR/unimplemented_pat.rs:11:45
    |
 LL | type Binding = pattern_type!(Option<u32> is x);
-   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #123646 <https://github.com/rust-lang/rust/issues/123646> for more information
-   = help: add `#![feature(pattern_types)]` to the crate attributes to enable
-   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   |                                             ^
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0658`.