about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <github333195615777966@oli-obk.de>2025-02-06 13:48:12 +0000
committerOli Scherer <github333195615777966@oli-obk.de>2025-02-11 08:51:05 +0000
commit6d7ce4e893003cc652428ec02eb752bba63645e2 (patch)
treecaf8b8ce21c274ebb92c49fa29b92c7ccd0a6f49
parentc182ce9cbc8c29ebc1b4559d027df545e6cdd287 (diff)
downloadrust-6d7ce4e893003cc652428ec02eb752bba63645e2.tar.gz
rust-6d7ce4e893003cc652428ec02eb752bba63645e2.zip
Add a TyPat in the AST to reuse the generic arg lowering logic
-rw-r--r--compiler/rustc_ast/src/ast.rs23
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs20
-rw-r--r--compiler/rustc_ast/src/visit.rs17
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs80
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs24
-rw-r--r--compiler/rustc_builtin_macros/src/pattern_type.rs18
-rw-r--r--compiler/rustc_resolve/src/late.rs15
-rw-r--r--src/tools/rustfmt/src/patterns.rs87
-rw-r--r--src/tools/rustfmt/src/spanned.rs2
-rw-r--r--src/tools/rustfmt/src/types.rs16
-rw-r--r--tests/ui/type/pattern_types/assoc_const.default.stderr83
-rw-r--r--tests/ui/type/pattern_types/assoc_const.rs12
-rw-r--r--tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.rs2
-rw-r--r--tests/ui/type/pattern_types/bad_const_generics_args_on_const_param.stderr11
-rw-r--r--tests/ui/type/pattern_types/const_block.rs2
-rw-r--r--tests/ui/type/pattern_types/const_block.stderr72
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types.rs1
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types.stderr8
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types2.rs2
-rw-r--r--tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr8
-rw-r--r--tests/ui/unpretty/expanded-exhaustive.stdout2
21 files changed, 241 insertions, 264 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index deee3a597ae..29c1d34a125 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -2249,7 +2249,7 @@ pub enum TyKind {
     CVarArgs,
     /// Pattern types like `pattern_type!(u32 is 1..=)`, which is the same as `NonZero<u32>`,
     /// just as part of the type system.
-    Pat(P<Ty>, P<Pat>),
+    Pat(P<Ty>, P<TyPat>),
     /// Sometimes we need a dummy value when no error has occurred.
     Dummy,
     /// Placeholder for a kind that has failed to be defined.
@@ -2277,6 +2277,27 @@ impl TyKind {
     }
 }
 
+/// A pattern type pattern.
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub struct TyPat {
+    pub id: NodeId,
+    pub kind: TyPatKind,
+    pub span: Span,
+    pub tokens: Option<LazyAttrTokenStream>,
+}
+
+/// All the different flavors of pattern that Rust recognizes.
+//
+// Adding a new variant? Please update `test_pat` in `tests/ui/macros/stringify.rs`.
+#[derive(Clone, Encodable, Decodable, Debug)]
+pub enum TyPatKind {
+    /// A range pattern (e.g., `1...2`, `1..2`, `1..`, `..2`, `1..=2`, `..=2`).
+    Range(Option<P<AnonConst>>, Option<P<AnonConst>>, Spanned<RangeEnd>),
+
+    /// Placeholder for a pattern that wasn't syntactically well formed in some way.
+    Err(ErrorGuaranteed),
+}
+
 /// Syntax used to declare a trait object.
 #[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
 #[repr(u8)]
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index a9961cca583..de9f049704a 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -210,6 +210,10 @@ pub trait MutVisitor: Sized {
         walk_ty(self, t);
     }
 
+    fn visit_ty_pat(&mut self, t: &mut P<TyPat>) {
+        walk_ty_pat(self, t);
+    }
+
     fn visit_lifetime(&mut self, l: &mut Lifetime) {
         walk_lifetime(self, l);
     }
@@ -570,7 +574,7 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
         TyKind::Paren(ty) => vis.visit_ty(ty),
         TyKind::Pat(ty, pat) => {
             vis.visit_ty(ty);
-            vis.visit_pat(pat);
+            vis.visit_ty_pat(pat);
         }
         TyKind::Path(qself, path) => {
             vis.visit_qself(qself);
@@ -594,6 +598,20 @@ pub fn walk_ty<T: MutVisitor>(vis: &mut T, ty: &mut P<Ty>) {
     vis.visit_span(span);
 }
 
+pub fn walk_ty_pat<T: MutVisitor>(vis: &mut T, ty: &mut P<TyPat>) {
+    let TyPat { id, kind, span, tokens } = ty.deref_mut();
+    vis.visit_id(id);
+    match kind {
+        TyPatKind::Range(start, end, _include_end) => {
+            visit_opt(start, |c| vis.visit_anon_const(c));
+            visit_opt(end, |c| vis.visit_anon_const(c));
+        }
+        TyPatKind::Err(_) => {}
+    }
+    visit_lazy_tts(vis, tokens);
+    vis.visit_span(span);
+}
+
 fn walk_foreign_mod<T: MutVisitor>(vis: &mut T, foreign_mod: &mut ForeignMod) {
     let ForeignMod { extern_span: _, safety, abi: _, items } = foreign_mod;
     visit_safety(vis, safety);
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 714b074f930..3242d414595 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -179,6 +179,9 @@ pub trait Visitor<'ast>: Sized {
     fn visit_ty(&mut self, t: &'ast Ty) -> Self::Result {
         walk_ty(self, t)
     }
+    fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
+        walk_ty_pat(self, t)
+    }
     fn visit_generic_param(&mut self, param: &'ast GenericParam) -> Self::Result {
         walk_generic_param(self, param)
     }
@@ -534,7 +537,7 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
         }
         TyKind::Pat(ty, pat) => {
             try_visit!(visitor.visit_ty(ty));
-            try_visit!(visitor.visit_pat(pat));
+            try_visit!(visitor.visit_ty_pat(pat));
         }
         TyKind::Array(ty, length) => {
             try_visit!(visitor.visit_ty(ty));
@@ -555,6 +558,18 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) -> V::Result {
     V::Result::output()
 }
 
+pub fn walk_ty_pat<'a, V: Visitor<'a>>(visitor: &mut V, tp: &'a TyPat) -> V::Result {
+    let TyPat { id: _, kind, span: _, tokens: _ } = tp;
+    match kind {
+        TyPatKind::Range(start, end, _include_end) => {
+            visit_opt!(visitor, visit_anon_const, start);
+            visit_opt!(visitor, visit_anon_const, end);
+        }
+        TyPatKind::Err(_) => {}
+    }
+    V::Result::output()
+}
+
 fn walk_qself<'a, V: Visitor<'a>>(visitor: &mut V, qself: &'a Option<P<QSelf>>) -> V::Result {
     if let Some(qself) = qself {
         let QSelf { ty, path_span: _, position: _ } = &**qself;
diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs
index bb9b2a13185..e1f3afbcf59 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::{DefKind, Res};
+use rustc_hir::def::Res;
 use rustc_middle::span_bug;
 use rustc_span::source_map::{Spanned, respan};
-use rustc_span::{Ident, Span, kw};
+use rustc_span::{Ident, Span};
 
 use super::errors::{
     ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
@@ -430,78 +430,20 @@ 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> {
+    pub(crate) fn lower_ty_pat(&mut self, pattern: &TyPat) -> &'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> {
+    fn lower_ty_pat_mut(&mut self, pattern: &TyPat) -> 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"),
-                    );
-                }
-            }
+        let node = match &pattern.kind {
+            TyPatKind::Range(e1, e2, Spanned { node: end, .. }) => hir::TyPatKind::Range(
+                e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
+                e2.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)),
+                self.lower_range_end(end, e2.is_some()),
+            ),
+            TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar),
         };
 
         hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index eeec24e5ea4..0bf5de3ef89 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -1148,6 +1148,28 @@ impl<'a> State<'a> {
         }
     }
 
+    pub fn print_ty_pat(&mut self, pat: &ast::TyPat) {
+        match &pat.kind {
+            rustc_ast::TyPatKind::Range(start, end, include_end) => {
+                if let Some(start) = start {
+                    self.print_expr_anon_const(start, &[]);
+                }
+                self.word("..");
+                if let Some(end) = end {
+                    if let RangeEnd::Included(_) = include_end.node {
+                        self.word("=");
+                    }
+                    self.print_expr_anon_const(end, &[]);
+                }
+            }
+            rustc_ast::TyPatKind::Err(_) => {
+                self.popen();
+                self.word("/*ERROR*/");
+                self.pclose();
+            }
+        }
+    }
+
     pub fn print_type(&mut self, ty: &ast::Ty) {
         self.maybe_print_comment(ty.span.lo());
         self.ibox(0);
@@ -1252,7 +1274,7 @@ impl<'a> State<'a> {
             ast::TyKind::Pat(ty, pat) => {
                 self.print_type(ty);
                 self.word(" is ");
-                self.print_pat(pat);
+                self.print_ty_pat(pat);
             }
         }
         self.end();
diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs
index a600a9f316a..a55c7e962d0 100644
--- a/compiler/rustc_builtin_macros/src/pattern_type.rs
+++ b/compiler/rustc_builtin_macros/src/pattern_type.rs
@@ -1,6 +1,6 @@
 use rustc_ast::ptr::P;
 use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::{Pat, Ty, ast};
+use rustc_ast::{AnonConst, DUMMY_NODE_ID, Ty, TyPat, TyPatKind, ast};
 use rustc_errors::PResult;
 use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
 use rustc_parse::exp;
@@ -21,12 +21,24 @@ pub(crate) fn expand<'cx>(
     ExpandResult::Ready(base::MacEager::ty(cx.ty(sp, ast::TyKind::Pat(ty, pat))))
 }
 
-fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<Pat>)> {
+fn parse_pat_ty<'a>(cx: &mut ExtCtxt<'a>, stream: TokenStream) -> PResult<'a, (P<Ty>, P<TyPat>)> {
     let mut parser = cx.new_parser_from_tts(stream);
 
     let ty = parser.parse_ty()?;
     parser.expect_keyword(exp!(Is))?;
-    let pat = parser.parse_pat_no_top_alt(None, None)?;
+    let pat = parser.parse_pat_no_top_alt(None, None)?.into_inner();
+
+    let kind = match pat.kind {
+        ast::PatKind::Range(start, end, include_end) => TyPatKind::Range(
+            start.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
+            end.map(|value| P(AnonConst { id: DUMMY_NODE_ID, value })),
+            include_end,
+        ),
+        ast::PatKind::Err(guar) => TyPatKind::Err(guar),
+        _ => TyPatKind::Err(cx.dcx().span_err(pat.span, "pattern not supported in pattern types")),
+    };
+
+    let pat = P(TyPat { id: pat.id, kind, span: pat.span, tokens: pat.tokens });
 
     Ok((ty, pat))
 }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 508bd831ccb..03aeb8720ca 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -923,6 +923,21 @@ impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'r
         self.diag_metadata.current_trait_object = prev;
         self.diag_metadata.current_type_path = prev_ty;
     }
+
+    fn visit_ty_pat(&mut self, t: &'ast TyPat) -> Self::Result {
+        match &t.kind {
+            TyPatKind::Range(start, end, _) => {
+                if let Some(start) = start {
+                    self.resolve_anon_const(start, AnonConstKind::ConstArg(IsRepeatExpr::No));
+                }
+                if let Some(end) = end {
+                    self.resolve_anon_const(end, AnonConstKind::ConstArg(IsRepeatExpr::No));
+                }
+            }
+            TyPatKind::Err(_) => {}
+        }
+    }
+
     fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
         let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo());
         self.with_generic_param_rib(
diff --git a/src/tools/rustfmt/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs
index 1d88726d945..bafed41e39f 100644
--- a/src/tools/rustfmt/src/patterns.rs
+++ b/src/tools/rustfmt/src/patterns.rs
@@ -75,12 +75,12 @@ fn is_short_pattern_inner(context: &RewriteContext<'_>, pat: &ast::Pat) -> bool
     }
 }
 
-pub(crate) struct RangeOperand<'a> {
-    operand: &'a Option<ptr::P<ast::Expr>>,
-    pub(crate) span: Span,
+pub(crate) struct RangeOperand<'a, T> {
+    pub operand: &'a Option<ptr::P<T>>,
+    pub span: Span,
 }
 
-impl<'a> Rewrite for RangeOperand<'a> {
+impl<'a, T: Rewrite> Rewrite for RangeOperand<'a, T> {
     fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
         self.rewrite_result(context, shape).ok()
     }
@@ -259,40 +259,7 @@ impl Rewrite for Pat {
             }
             PatKind::Never => Err(RewriteError::Unknown),
             PatKind::Range(ref lhs, ref rhs, ref end_kind) => {
-                let infix = match end_kind.node {
-                    RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
-                    RangeEnd::Included(RangeSyntax::DotDotEq) => "..=",
-                    RangeEnd::Excluded => "..",
-                };
-                let infix = if context.config.spaces_around_ranges() {
-                    let lhs_spacing = match lhs {
-                        None => "",
-                        Some(_) => " ",
-                    };
-                    let rhs_spacing = match rhs {
-                        None => "",
-                        Some(_) => " ",
-                    };
-                    format!("{lhs_spacing}{infix}{rhs_spacing}")
-                } else {
-                    infix.to_owned()
-                };
-                let lspan = self.span.with_hi(end_kind.span.lo());
-                let rspan = self.span.with_lo(end_kind.span.hi());
-                rewrite_pair(
-                    &RangeOperand {
-                        operand: lhs,
-                        span: lspan,
-                    },
-                    &RangeOperand {
-                        operand: rhs,
-                        span: rspan,
-                    },
-                    PairParts::infix(&infix),
-                    context,
-                    shape,
-                    SeparatorPlace::Front,
-                )
+                rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span)
             }
             PatKind::Ref(ref pat, mutability) => {
                 let prefix = format!("&{}", format_mutability(mutability));
@@ -359,6 +326,50 @@ impl Rewrite for Pat {
     }
 }
 
+pub fn rewrite_range_pat<T: Rewrite>(
+    context: &RewriteContext<'_>,
+    shape: Shape,
+    lhs: &Option<ptr::P<T>>,
+    rhs: &Option<ptr::P<T>>,
+    end_kind: &rustc_span::source_map::Spanned<RangeEnd>,
+    span: Span,
+) -> RewriteResult {
+    let infix = match end_kind.node {
+        RangeEnd::Included(RangeSyntax::DotDotDot) => "...",
+        RangeEnd::Included(RangeSyntax::DotDotEq) => "..=",
+        RangeEnd::Excluded => "..",
+    };
+    let infix = if context.config.spaces_around_ranges() {
+        let lhs_spacing = match lhs {
+            None => "",
+            Some(_) => " ",
+        };
+        let rhs_spacing = match rhs {
+            None => "",
+            Some(_) => " ",
+        };
+        format!("{lhs_spacing}{infix}{rhs_spacing}")
+    } else {
+        infix.to_owned()
+    };
+    let lspan = span.with_hi(end_kind.span.lo());
+    let rspan = span.with_lo(end_kind.span.hi());
+    rewrite_pair(
+        &RangeOperand {
+            operand: lhs,
+            span: lspan,
+        },
+        &RangeOperand {
+            operand: rhs,
+            span: rspan,
+        },
+        PairParts::infix(&infix),
+        context,
+        shape,
+        SeparatorPlace::Front,
+    )
+}
+
 fn rewrite_struct_pat(
     qself: &Option<ptr::P<ast::QSelf>>,
     path: &ast::Path,
diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs
index 6b3e40b9115..e93eb53cd87 100644
--- a/src/tools/rustfmt/src/spanned.rs
+++ b/src/tools/rustfmt/src/spanned.rs
@@ -211,7 +211,7 @@ impl Spanned for ast::PreciseCapturingArg {
     }
 }
 
-impl<'a> Spanned for RangeOperand<'a> {
+impl<'a, T> Spanned for RangeOperand<'a, T> {
     fn span(&self) -> Span {
         self.span
     }
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index f8b713117f4..0009490e86f 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -18,6 +18,7 @@ use crate::lists::{
 use crate::macros::{MacroPosition, rewrite_macro};
 use crate::overflow;
 use crate::pairs::{PairParts, rewrite_pair};
+use crate::patterns::rewrite_range_pat;
 use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, RewriteResult};
 use crate::shape::Shape;
 use crate::source_map::SpanUtils;
@@ -1045,6 +1046,21 @@ impl Rewrite for ast::Ty {
     }
 }
 
+impl Rewrite for ast::TyPat {
+    fn rewrite(&self, context: &RewriteContext<'_>, shape: Shape) -> Option<String> {
+        self.rewrite_result(context, shape).ok()
+    }
+
+    fn rewrite_result(&self, context: &RewriteContext<'_>, shape: Shape) -> RewriteResult {
+        match self.kind {
+            ast::TyPatKind::Range(ref lhs, ref rhs, ref end_kind) => {
+                rewrite_range_pat(context, shape, lhs, rhs, end_kind, self.span)
+            }
+            ast::TyPatKind::Err(_) => Err(RewriteError::Unknown),
+        }
+    }
+}
+
 fn rewrite_bare_fn(
     bare_fn: &ast::BareFnTy,
     span: Span,
diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr
index c5d9691a029..8cff0cee7b9 100644
--- a/tests/ui/type/pattern_types/assoc_const.default.stderr
+++ b/tests/ui/type/pattern_types/assoc_const.default.stderr
@@ -1,79 +1,38 @@
-error[E0658]: wraparound pattern type ranges cause monomorphization time errors
-  --> $DIR/assoc_const.rs:17:19
+error: generic parameters may not be used in const operations
+  --> $DIR/assoc_const.rs:17:41
    |
 LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                         ^ cannot perform const operation using `T`
    |
-   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
-   = help: add `#![feature(generic_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
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error[E0658]: wraparound pattern type ranges cause monomorphization time errors
-  --> $DIR/assoc_const.rs:17:19
+error: generic parameters may not be used in const operations
+  --> $DIR/assoc_const.rs:17:61
    |
 LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                             ^ cannot perform const operation using `T`
    |
-   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
-   = help: add `#![feature(generic_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
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-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[E0658]: wraparound pattern type ranges cause monomorphization time errors
-  --> $DIR/assoc_const.rs:22:19
-   |
-LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
-   = help: add `#![feature(generic_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]: wraparound pattern type ranges cause monomorphization time errors
-  --> $DIR/assoc_const.rs:22:19
-   |
-LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
-   = help: add `#![feature(generic_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
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error: constant expression depends on a generic parameter
-  --> $DIR/assoc_const.rs:22:19
+error: generic parameters may not be used in const operations
+  --> $DIR/assoc_const.rs:20:40
    |
 LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                        ^^^^^^^^ cannot perform const operation using `T`
    |
-   = note: this may fail depending on what value the parameter takes
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error: constant expression depends on a generic parameter
-  --> $DIR/assoc_const.rs:22:19
+error: generic parameters may not be used in const operations
+  --> $DIR/assoc_const.rs:20:51
    |
 LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
-   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                   ^^^^^^ cannot perform const operation using `T`
    |
-   = note: this may fail depending on what value the parameter takes
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+   = note: type parameters may not be used in const expressions
+   = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions
 
-error: aborting due to 8 previous errors
+error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/type/pattern_types/assoc_const.rs b/tests/ui/type/pattern_types/assoc_const.rs
index 87886587d51..90508801990 100644
--- a/tests/ui/type/pattern_types/assoc_const.rs
+++ b/tests/ui/type/pattern_types/assoc_const.rs
@@ -15,14 +15,10 @@ trait Foo {
 }
 
 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
-//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
-//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
+//[default]~^ ERROR: generic parameters may not be used in const operations
+//[default]~| ERROR: generic parameters may not be used in const operations
 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
-//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
-//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
+//[default]~^ ERROR: generic parameters may not be used in const operations
+//[default]~| ERROR: generic parameters may not be used in const operations
 
 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 0f10bf8ce62..c28fda6f91a 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
@@ -5,7 +5,7 @@
 //@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
 //@ rustc-env:RUST_BACKTRACE=0
 
-#![feature(pattern_types, pattern_type_macro)]
+#![feature(pattern_types, pattern_type_macro, generic_const_exprs)]
 #![allow(internal_features)]
 
 type Pat<const START: u32, const END: u32> =
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 fbe80a19863..ffc6068eb17 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,4 +1,11 @@
-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
+warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad_const_generics_args_on_const_param.rs:8:47
+   |
+LL | #![feature(pattern_types, pattern_type_macro, generic_const_exprs)]
+   |                                               ^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
+   = 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 = ()>);
@@ -10,5 +17,5 @@ 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
+error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/type/pattern_types/const_block.rs b/tests/ui/type/pattern_types/const_block.rs
index 49c87f4fa0d..ed19b10671a 100644
--- a/tests/ui/type/pattern_types/const_block.rs
+++ b/tests/ui/type/pattern_types/const_block.rs
@@ -1,10 +1,10 @@
 #![feature(pattern_types)]
 #![feature(pattern_type_macro)]
 #![feature(inline_const_pat)]
+//@ check-pass
 
 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
deleted file mode 100644
index 82b616105af..00000000000
--- a/tests/ui/type/pattern_types/const_block.stderr
+++ /dev/null
@@ -1,72 +0,0 @@
-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/feature-gate-pattern_types.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
index b90ba478402..b4f4bd656f5 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.rs
@@ -12,3 +12,4 @@ type Positive = pattern_type!(i32 is 0..);
 //~^ use of unstable library feature `pattern_type_macro`
 type Always = pattern_type!(Option<u32> is Some(_));
 //~^ use of unstable library feature `pattern_type_macro`
+//~| ERROR pattern not supported in pattern types
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
index 69239d68bdc..12508bcb54a 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types.stderr
@@ -48,6 +48,12 @@ LL | type Always = pattern_type!(Option<u32> is Some(_));
    = help: add `#![feature(pattern_type_macro)]` 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 5 previous errors
+error: pattern not supported in pattern types
+  --> $DIR/feature-gate-pattern_types.rs:13:44
+   |
+LL | type Always = pattern_type!(Option<u32> is Some(_));
+   |                                            ^^^^^^^
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs
index 50c355c8de6..c6b4b325fa3 100644
--- a/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types2.rs
@@ -1,5 +1,4 @@
 //@ compile-flags: -Zno-analysis
-//@ check-pass
 
 #![feature(pattern_type_macro)]
 
@@ -10,3 +9,4 @@ type Percent = pattern_type!(u32 is 0..=100);
 type Negative = pattern_type!(i32 is ..=0);
 type Positive = pattern_type!(i32 is 0..);
 type Always = pattern_type!(Option<u32> is Some(_));
+//~^ ERROR: pattern not supported in pattern types
diff --git a/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr b/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr
new file mode 100644
index 00000000000..81bf9dea0e2
--- /dev/null
+++ b/tests/ui/type/pattern_types/feature-gate-pattern_types2.stderr
@@ -0,0 +1,8 @@
+error: pattern not supported in pattern types
+  --> $DIR/feature-gate-pattern_types2.rs:11:44
+   |
+LL | type Always = pattern_type!(Option<u32> is Some(_));
+   |                                            ^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/unpretty/expanded-exhaustive.stdout b/tests/ui/unpretty/expanded-exhaustive.stdout
index 11066c90edb..19ae66f7a07 100644
--- a/tests/ui/unpretty/expanded-exhaustive.stdout
+++ b/tests/ui/unpretty/expanded-exhaustive.stdout
@@ -678,7 +678,7 @@ mod types {
         /*! FIXME: todo */
     }
     /// TyKind::Pat
-    fn ty_pat() { let _: u32 is 1..; }
+    fn ty_pat() { let _: u32 is const 1..; }
 }
 mod visibilities {
     /// VisibilityKind::Public