about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorOli Scherer <github333195615777966@oli-obk.de>2025-02-05 15:22:10 +0000
committerOli Scherer <github333195615777966@oli-obk.de>2025-03-06 10:47:40 +0000
commite8f7a382be12a812b7d73f58967f740a0cf9d9af (patch)
tree81db85c4e7c42a85898967fe3b8601f9377d15e7 /compiler
parent0e7b2835735fc7fee08505fa6c14670bc7ee7601 (diff)
downloadrust-e8f7a382be12a812b7d73f58967f740a0cf9d9af.tar.gz
rust-e8f7a382be12a812b7d73f58967f740a0cf9d9af.zip
Remove the `Option` part of range ends in the HIR
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs4
-rw-r--r--compiler/rustc_ast_lowering/src/pat.rs122
-rw-r--r--compiler/rustc_hir/src/hir.rs2
-rw-r--r--compiler/rustc_hir/src/intravisit.rs6
-rw-r--r--compiler/rustc_hir/src/lang_items.rs3
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl3
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/errors/pattern_types.rs14
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs90
-rw-r--r--compiler/rustc_hir_analysis/src/variance/constraints.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs15
-rw-r--r--compiler/rustc_lint/src/types.rs13
-rw-r--r--compiler/rustc_middle/src/ty/flags.rs2
-rw-r--r--compiler/rustc_middle/src/ty/pattern.rs7
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs15
-rw-r--r--compiler/rustc_middle/src/ty/walk.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_internal/internal.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/convert/ty.rs4
-rw-r--r--compiler/rustc_span/src/hygiene.rs3
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_symbol_mangling/src/v0.rs11
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs9
23 files changed, 167 insertions, 172 deletions
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index c0188dde565..ee131bb51f6 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -136,6 +136,7 @@ struct LoweringContext<'a, 'hir> {
 
     allow_try_trait: Arc<[Symbol]>,
     allow_gen_future: Arc<[Symbol]>,
+    allow_pattern_type: Arc<[Symbol]>,
     allow_async_iterator: Arc<[Symbol]>,
     allow_for_await: Arc<[Symbol]>,
     allow_async_fn_traits: Arc<[Symbol]>,
@@ -176,6 +177,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             impl_trait_defs: Vec::new(),
             impl_trait_bounds: Vec::new(),
             allow_try_trait: [sym::try_trait_v2, sym::yeet_desugar_details].into(),
+            allow_pattern_type: [sym::pattern_types, sym::pattern_type_range_trait].into(),
             allow_gen_future: if tcx.features().async_fn_track_caller() {
                 [sym::gen_future, sym::closure_track_caller].into()
             } else {
@@ -1365,7 +1367,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 }
             }
             TyKind::Pat(ty, pat) => {
-                hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat))
+                hir::TyKind::Pat(self.lower_ty(ty, itctx), self.lower_ty_pat(pat, ty.span))
             }
             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 2dcfe7c745d..728981dea5f 100644
--- a/compiler/rustc_ast_lowering/src/pat.rs
+++ b/compiler/rustc_ast_lowering/src/pat.rs
@@ -3,11 +3,11 @@ use std::sync::Arc;
 use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_hir as hir;
-use rustc_hir::def::Res;
+use rustc_hir::def::{DefKind, Res};
+use rustc_hir::{self as hir, LangItem};
 use rustc_middle::span_bug;
 use rustc_span::source_map::{Spanned, respan};
-use rustc_span::{Ident, Span};
+use rustc_span::{DesugaringKind, Ident, Span, kw};
 
 use super::errors::{
     ArbitraryExpressionInPattern, ExtraDoubleDot, MisplacedDoubleDot, SubTupleBinding,
@@ -430,22 +430,124 @@ 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: &TyPat) -> &'hir hir::TyPat<'hir> {
-        self.arena.alloc(self.lower_ty_pat_mut(pattern))
+    pub(crate) fn lower_ty_pat(
+        &mut self,
+        pattern: &TyPat,
+        base_type: Span,
+    ) -> &'hir hir::TyPat<'hir> {
+        self.arena.alloc(self.lower_ty_pat_mut(pattern, base_type))
     }
 
-    fn lower_ty_pat_mut(&mut self, pattern: &TyPat) -> hir::TyPat<'hir> {
+    fn lower_ty_pat_mut(&mut self, pattern: &TyPat, base_type: Span) -> hir::TyPat<'hir> {
         // loop here to avoid recursion
         let pat_hir_id = self.lower_node_id(pattern.id);
         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::Range(e1, e2, Spanned { node: end, span }) => hir::TyPatKind::Range(
+                e1.as_deref().map(|e| self.lower_anon_const_to_const_arg(e)).unwrap_or_else(|| {
+                    self.lower_ty_pat_range_end(
+                        hir::LangItem::RangeMin,
+                        span.shrink_to_lo(),
+                        base_type,
+                    )
+                }),
+                e2.as_deref()
+                    .map(|e| match end {
+                        RangeEnd::Included(..) => self.lower_anon_const_to_const_arg(e),
+                        RangeEnd::Excluded => self.lower_excluded_range_end(e),
+                    })
+                    .unwrap_or_else(|| {
+                        self.lower_ty_pat_range_end(
+                            hir::LangItem::RangeMax,
+                            span.shrink_to_hi(),
+                            base_type,
+                        )
+                    }),
             ),
             TyPatKind::Err(guar) => hir::TyPatKind::Err(*guar),
         };
 
         hir::TyPat { hir_id: pat_hir_id, kind: node, span: self.lower_span(pattern.span) }
     }
+
+    /// Lowers the range end of an exclusive range (`2..5`) to an inclusive range 2..=(5 - 1).
+    /// This way the type system doesn't have to handle the distinction between inclusive/exclusive ranges.
+    fn lower_excluded_range_end(&mut self, e: &AnonConst) -> &'hir hir::ConstArg<'hir> {
+        let span = self.lower_span(e.value.span);
+        let unstable_span = self.mark_span_with_reason(
+            DesugaringKind::PatTyRange,
+            span,
+            Some(Arc::clone(&self.allow_pattern_type)),
+        );
+        let anon_const = self.with_new_scopes(span, |this| {
+            let def_id = this.local_def_id(e.id);
+            let hir_id = this.lower_node_id(e.id);
+            let body = this.lower_body(|this| {
+                // Need to use a custom function as we can't just subtract `1` from a `char`.
+                let kind = hir::ExprKind::Path(this.make_lang_item_qpath(
+                    hir::LangItem::RangeSub,
+                    unstable_span,
+                    None,
+                ));
+                let fn_def = this.arena.alloc(hir::Expr { hir_id: this.next_id(), kind, span });
+                let args = this.arena.alloc([this.lower_expr_mut(&e.value)]);
+                (
+                    &[],
+                    hir::Expr {
+                        hir_id: this.next_id(),
+                        kind: hir::ExprKind::Call(fn_def, args),
+                        span,
+                    },
+                )
+            });
+            hir::AnonConst { def_id, hir_id, body, span }
+        });
+        self.arena.alloc(hir::ConstArg {
+            hir_id: self.next_id(),
+            kind: hir::ConstArgKind::Anon(self.arena.alloc(anon_const)),
+        })
+    }
+
+    /// When a range has no end specified (`1..` or `1..=`) or no start specified (`..5` or `..=5`),
+    /// we instead use a constant of the MAX/MIN of the type.
+    /// This way the type system does not have to handle the lack of a start/end.
+    fn lower_ty_pat_range_end(
+        &mut self,
+        lang_item: LangItem,
+        span: Span,
+        base_type: Span,
+    ) -> &'hir hir::ConstArg<'hir> {
+        let parent_def_id = self.current_hir_id_owner.def_id;
+        let node_id = self.next_node_id();
+
+        // Add a definition for the in-band const def.
+        // We're generating a range end that didn't exist in the AST,
+        // so the def collector didn't create the def ahead of time. That's why we have to do
+        // it here.
+        let def_id = self.create_def(parent_def_id, node_id, kw::Empty, DefKind::AnonConst, span);
+        let hir_id = self.lower_node_id(node_id);
+
+        let unstable_span = self.mark_span_with_reason(
+            DesugaringKind::PatTyRange,
+            self.lower_span(span),
+            Some(Arc::clone(&self.allow_pattern_type)),
+        );
+        let span = self.lower_span(base_type);
+
+        let path_expr = hir::Expr {
+            hir_id: self.next_id(),
+            kind: hir::ExprKind::Path(self.make_lang_item_qpath(lang_item, unstable_span, None)),
+            span,
+        };
+
+        let ct = self.with_new_scopes(span, |this| {
+            self.arena.alloc(hir::AnonConst {
+                def_id,
+                hir_id,
+                body: this.lower_body(|_this| (&[], path_expr)),
+                span,
+            })
+        });
+        let hir_id = self.next_id();
+        self.arena.alloc(hir::ConstArg { kind: hir::ConstArgKind::Anon(ct), hir_id })
+    }
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 3b506039025..df305e6e769 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -1668,7 +1668,7 @@ 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),
+    Range(&'hir ConstArg<'hir>, &'hir ConstArg<'hir>),
 
     /// A placeholder for a pattern that wasn't well formed in some way.
     Err(ErrorGuaranteed),
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index e349e23f7dc..41eb5b45bd1 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -708,9 +708,9 @@ pub fn walk_arm<'v, V: Visitor<'v>>(visitor: &mut V, arm: &'v Arm<'v>) -> V::Res
 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::Range(lower_bound, upper_bound) => {
+            try_visit!(visitor.visit_const_arg_unambig(lower_bound));
+            try_visit!(visitor.visit_const_arg_unambig(upper_bound));
         }
         TyPatKind::Err(_) => (),
     }
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index f5626937ec4..c3b14a4e06c 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -418,6 +418,9 @@ language_item_table! {
     Range,                   sym::Range,               range_struct,               Target::Struct,         GenericRequirement::None;
     RangeToInclusive,        sym::RangeToInclusive,    range_to_inclusive_struct,  Target::Struct,         GenericRequirement::None;
     RangeTo,                 sym::RangeTo,             range_to_struct,            Target::Struct,         GenericRequirement::None;
+    RangeMax,                sym::RangeMax,            range_max,                  Target::AssocConst,     GenericRequirement::Exact(0);
+    RangeMin,                sym::RangeMin,            range_min,                  Target::AssocConst,     GenericRequirement::Exact(0);
+    RangeSub,                sym::RangeSub,            range_sub,                  Target::Method(MethodKind::Trait { body: false }),     GenericRequirement::Exact(0);
 
     // `new_range` types that are `Copy + IntoIterator`
     RangeFromCopy,           sym::RangeFromCopy,       range_from_copy_struct,     Target::Struct,         GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 3f75cce0092..d16aba197fe 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -244,9 +244,6 @@ hir_analysis_inherent_ty_outside_relevant = cannot define inherent `impl` for a
     .help = consider moving this inherent impl into the crate defining the type if possible
     .span_help = alternatively add `#[rustc_allow_incoherent_impl]` to the relevant impl items
 
-hir_analysis_invalid_base_type = `{$ty}` is not a valid base type for range patterns
-    .note = range patterns only support integers
-
 hir_analysis_invalid_generic_receiver_ty = invalid generic `self` parameter type: `{$receiver_ty}`
     .note = type of `self` must not be a method generic parameter type
 
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 852533ff5c9..f3e1e89812c 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -11,8 +11,6 @@ use rustc_middle::ty::Ty;
 use rustc_span::{Ident, Span, Symbol};
 
 use crate::fluent_generated as fluent;
-mod pattern_types;
-pub(crate) use pattern_types::*;
 pub(crate) mod wrong_number_of_generic_args;
 
 mod precise_captures;
diff --git a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs b/compiler/rustc_hir_analysis/src/errors/pattern_types.rs
deleted file mode 100644
index ec7b3aaa1c1..00000000000
--- a/compiler/rustc_hir_analysis/src/errors/pattern_types.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-use rustc_macros::Diagnostic;
-use rustc_middle::ty::Ty;
-use rustc_span::Span;
-
-#[derive(Diagnostic)]
-#[diag(hir_analysis_invalid_base_type)]
-pub(crate) struct InvalidBaseType<'tcx> {
-    pub ty: Ty<'tcx>,
-    #[primary_span]
-    pub ty_span: Span,
-    pub pat: &'static str,
-    #[note]
-    pub pat_span: Span,
-}
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 21581d304d9..dd6c40bfbb8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -21,9 +21,8 @@ pub mod generics;
 mod lint;
 
 use std::assert_matches::assert_matches;
-use std::{char, slice};
+use std::slice;
 
-use rustc_abi::Size;
 use rustc_ast::TraitObjectSyntax;
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_errors::codes::*;
@@ -32,7 +31,7 @@ use rustc_errors::{
 };
 use rustc_hir::def::{CtorKind, CtorOf, DefKind, Namespace, Res};
 use rustc_hir::def_id::{DefId, LocalDefId};
-use rustc_hir::{self as hir, AnonConst, ConstArg, GenericArg, GenericArgs, HirId};
+use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId};
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::ObligationCause;
 use rustc_middle::middle::stability::AllowUnstable;
@@ -56,9 +55,7 @@ use tracing::{debug, instrument};
 
 use self::errors::assoc_kind_str;
 use crate::check::check_abi_fn_ptr;
-use crate::errors::{
-    AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType, NoVariantNamed,
-};
+use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, NoVariantNamed};
 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;
@@ -2693,25 +2690,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 let ty_span = ty.span;
                 let ty = self.lower_ty(ty);
                 let pat_ty = match pat.kind {
-                    hir::TyPatKind::Range(start, end, include_end) => {
+                    hir::TyPatKind::Range(start, end) => {
                         let (ty, start, end) = match ty.kind() {
+                            // Keep this list of types in sync with the list of types that
+                            // the `RangePattern` trait is implemented for.
                             ty::Int(_) | ty::Uint(_) | ty::Char => {
-                                let (start, end) = self.lower_ty_pat_range(ty, start, end);
+                                let start = self.lower_const_arg(start, FeedConstTy::No);
+                                let end = self.lower_const_arg(end, FeedConstTy::No);
                                 (ty, start, end)
                             }
                             _ => {
-                                let guar = self.dcx().emit_err(InvalidBaseType {
-                                    ty,
-                                    pat: "range",
+                                let guar = self.dcx().span_delayed_bug(
                                     ty_span,
-                                    pat_span: pat.span,
-                                });
+                                    "invalid base type for range pattern",
+                                );
                                 let errc = ty::Const::new_error(tcx, guar);
                                 (Ty::new_error(tcx, guar), errc, errc)
                             }
                         };
 
-                        let pat = tcx.mk_pat(ty::PatternKind::Range { start, end, include_end });
+                        let pat = tcx.mk_pat(ty::PatternKind::Range { start, end });
                         Ty::new_pat(tcx, ty, pat)
                     }
                     hir::TyPatKind::Err(e) => Ty::new_error(tcx, e),
@@ -2726,70 +2724,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         result_ty
     }
 
-    fn lower_ty_pat_range(
-        &self,
-        base: Ty<'tcx>,
-        start: Option<&ConstArg<'tcx>>,
-        end: Option<&ConstArg<'tcx>>,
-    ) -> (ty::Const<'tcx>, ty::Const<'tcx>) {
-        let tcx = self.tcx();
-        let size = match base.kind() {
-            ty::Int(i) => {
-                i.bit_width().map_or(tcx.data_layout.pointer_size, |bits| Size::from_bits(bits))
-            }
-            ty::Uint(ui) => {
-                ui.bit_width().map_or(tcx.data_layout.pointer_size, |bits| Size::from_bits(bits))
-            }
-            ty::Char => Size::from_bytes(4),
-            _ => unreachable!(),
-        };
-        let start =
-            start.map(|expr| self.lower_const_arg(expr, FeedConstTy::No)).unwrap_or_else(|| {
-                match base.kind() {
-                    ty::Char | ty::Uint(_) => ty::Const::new_value(
-                        tcx,
-                        ty::ValTree::from_scalar_int(ty::ScalarInt::null(size)),
-                        base,
-                    ),
-                    ty::Int(_) => ty::Const::new_value(
-                        tcx,
-                        ty::ValTree::from_scalar_int(
-                            ty::ScalarInt::truncate_from_int(size.signed_int_min(), size).0,
-                        ),
-                        base,
-                    ),
-                    _ => unreachable!(),
-                }
-            });
-        let end = end.map(|expr| self.lower_const_arg(expr, FeedConstTy::No)).unwrap_or_else(
-            || match base.kind() {
-                ty::Char => ty::Const::new_value(
-                    tcx,
-                    ty::ValTree::from_scalar_int(
-                        ty::ScalarInt::truncate_from_uint(char::MAX, size).0,
-                    ),
-                    base,
-                ),
-                ty::Uint(_) => ty::Const::new_value(
-                    tcx,
-                    ty::ValTree::from_scalar_int(
-                        ty::ScalarInt::truncate_from_uint(size.unsigned_int_max(), size).0,
-                    ),
-                    base,
-                ),
-                ty::Int(_) => ty::Const::new_value(
-                    tcx,
-                    ty::ValTree::from_scalar_int(
-                        ty::ScalarInt::truncate_from_int(size.signed_int_max(), size).0,
-                    ),
-                    base,
-                ),
-                _ => unreachable!(),
-            },
-        );
-        (start, end)
-    }
-
     /// Lower an opaque type (i.e., an existential impl-Trait type) from the HIR.
     #[instrument(level = "debug", skip(self), ret)]
     fn lower_opaque_ty(&self, def_id: LocalDefId, in_trait: bool) -> Ty<'tcx> {
diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs
index 4b336769cfb..8475903c68f 100644
--- a/compiler/rustc_hir_analysis/src/variance/constraints.rs
+++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs
@@ -252,7 +252,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
             ty::Pat(typ, pat) => {
                 match *pat {
-                    ty::PatternKind::Range { start, end, include_end: _ } => {
+                    ty::PatternKind::Range { start, end } => {
                         self.add_constraints_from_const(current, start, variance);
                         self.add_constraints_from_const(current, end, variance);
                     }
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 1658c8dac67..147b42c0490 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1943,17 +1943,10 @@ impl<'a> State<'a> {
         // 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::Range(begin, end) => {
+                self.print_const_arg(begin);
+                self.word("..=");
+                self.print_const_arg(end);
             }
             TyPatKind::Err(_) => {
                 self.popen();
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index d873d9fca64..fcadbfc3c4a 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -5,7 +5,7 @@ use rustc_abi::{BackendRepr, TagEncoding, VariantIdx, Variants, WrappingRange};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::DiagMessage;
 use rustc_hir::intravisit::VisitorExt;
-use rustc_hir::{AmbigArg, Expr, ExprKind, HirId, LangItem, RangeEnd};
+use rustc_hir::{AmbigArg, Expr, ExprKind, HirId, LangItem};
 use rustc_middle::bug;
 use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton};
 use rustc_middle::ty::{
@@ -882,16 +882,13 @@ fn ty_is_known_nonnull<'tcx>(
                 || Option::unwrap_or_default(
                     try {
                         match **pat {
-                            ty::PatternKind::Range { start, end, include_end } => {
+                            ty::PatternKind::Range { start, end } => {
                                 let start = start.try_to_value()?.try_to_bits(tcx, typing_env)?;
                                 let end = end.try_to_value()?.try_to_bits(tcx, typing_env)?;
 
-                                match include_end {
-                                    // This also works for negative numbers, as we just need
-                                    // to ensure we aren't wrapping over zero.
-                                    RangeEnd::Included => start > 0 && end >= start,
-                                    RangeEnd::Excluded => start > 0 && end > start,
-                                }
+                                // This also works for negative numbers, as we just need
+                                // to ensure we aren't wrapping over zero.
+                                start > 0 && end >= start
                             }
                         }
                     },
diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs
index c08d78e25b8..0b8f0e8cd41 100644
--- a/compiler/rustc_middle/src/ty/flags.rs
+++ b/compiler/rustc_middle/src/ty/flags.rs
@@ -220,7 +220,7 @@ impl FlagComputation {
             &ty::Pat(ty, pat) => {
                 self.add_ty(ty);
                 match *pat {
-                    ty::PatternKind::Range { start, end, include_end: _ } => {
+                    ty::PatternKind::Range { start, end } => {
                         self.add_const(start);
                         self.add_const(end);
                     }
diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs
index a1dfd2e8d34..89dadb36ad6 100644
--- a/compiler/rustc_middle/src/ty/pattern.rs
+++ b/compiler/rustc_middle/src/ty/pattern.rs
@@ -1,7 +1,6 @@
 use std::fmt;
 
 use rustc_data_structures::intern::Interned;
-use rustc_hir::RangeEnd;
 use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
 
 use crate::ty;
@@ -27,8 +26,8 @@ impl<'tcx> fmt::Debug for Pattern<'tcx> {
 impl<'tcx> fmt::Debug for PatternKind<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         match *self {
-            PatternKind::Range { start, end, include_end } => {
-                write!(f, "{start}{include_end}{end}")
+            PatternKind::Range { start, end } => {
+                write!(f, "{start}..={end}")
             }
         }
     }
@@ -37,5 +36,5 @@ impl<'tcx> fmt::Debug for PatternKind<'tcx> {
 #[derive(Clone, PartialEq, Eq, Hash)]
 #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
 pub enum PatternKind<'tcx> {
-    Range { start: ty::Const<'tcx>, end: ty::Const<'tcx>, include_end: RangeEnd },
+    Range { start: ty::Const<'tcx>, end: ty::Const<'tcx> },
 }
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 6d5cc42065f..b1dfcb80bde 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -51,21 +51,12 @@ impl<'tcx> Relate<TyCtxt<'tcx>> for ty::Pattern<'tcx> {
     ) -> RelateResult<'tcx, Self> {
         match (&*a, &*b) {
             (
-                &ty::PatternKind::Range { start: start_a, end: end_a, include_end: inc_a },
-                &ty::PatternKind::Range { start: start_b, end: end_b, include_end: inc_b },
+                &ty::PatternKind::Range { start: start_a, end: end_a },
+                &ty::PatternKind::Range { start: start_b, end: end_b },
             ) => {
                 let start = relation.relate(start_a, start_b)?;
-                // FIXME(pattern_types): make equal patterns equal (`0..5` is the same as `0..=6`).
                 let end = relation.relate(end_a, end_b)?;
-                if inc_a == inc_b {
-                    Ok(relation.cx().mk_pat(ty::PatternKind::Range {
-                        start,
-                        end,
-                        include_end: inc_a,
-                    }))
-                } else {
-                    Err(TypeError::Mismatch)
-                }
+                Ok(relation.cx().mk_pat(ty::PatternKind::Range { start, end }))
             }
         }
     }
diff --git a/compiler/rustc_middle/src/ty/walk.rs b/compiler/rustc_middle/src/ty/walk.rs
index b31b7cac41e..a23316ae6fc 100644
--- a/compiler/rustc_middle/src/ty/walk.rs
+++ b/compiler/rustc_middle/src/ty/walk.rs
@@ -137,7 +137,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>)
 
             ty::Pat(ty, pat) => {
                 match *pat {
-                    ty::PatternKind::Range { start, end, include_end: _ } => {
+                    ty::PatternKind::Range { start, end } => {
                         stack.push(end.into());
                         stack.push(start.into());
                     }
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index a8c4cd660fd..bb2b2dea2f3 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -5,7 +5,6 @@
 
 // Prefer importing stable_mir over internal rustc constructs to make this file more readable.
 
-use rustc_hir::RangeEnd;
 use rustc_middle::ty::{self as rustc_ty, Const as InternalConst, Ty as InternalTy, TyCtxt};
 use rustc_span::Symbol;
 use stable_mir::abi::Layout;
@@ -89,10 +88,9 @@ impl RustcInternal for Pattern {
     type T<'tcx> = rustc_ty::Pattern<'tcx>;
     fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
         tcx.mk_pat(match self {
-            Pattern::Range { start, end, include_end } => rustc_ty::PatternKind::Range {
+            Pattern::Range { start, end, include_end: _ } => rustc_ty::PatternKind::Range {
                 start: start.as_ref().unwrap().internal(tables, tcx),
                 end: end.as_ref().unwrap().internal(tables, tcx),
-                include_end: if *include_end { RangeEnd::Included } else { RangeEnd::Excluded },
             },
         })
     }
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index f6a6a3c1737..aa0eac628dd 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -405,11 +405,11 @@ impl<'tcx> Stable<'tcx> for ty::Pattern<'tcx> {
 
     fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
         match **self {
-            ty::PatternKind::Range { start, end, include_end } => stable_mir::ty::Pattern::Range {
+            ty::PatternKind::Range { start, end } => stable_mir::ty::Pattern::Range {
                 // FIXME(SMIR): update data structures to not have an Option here anymore
                 start: Some(start.stable(tables)),
                 end: Some(end.stable(tables)),
-                include_end: matches!(include_end, rustc_hir::RangeEnd::Included),
+                include_end: true,
             },
         }
     }
diff --git a/compiler/rustc_span/src/hygiene.rs b/compiler/rustc_span/src/hygiene.rs
index 84e89ff4b7d..64982b858c6 100644
--- a/compiler/rustc_span/src/hygiene.rs
+++ b/compiler/rustc_span/src/hygiene.rs
@@ -1173,6 +1173,8 @@ pub enum DesugaringKind {
     BoundModifier,
     /// Calls to contract checks (`#[requires]` to precond, `#[ensures]` to postcond)
     Contract,
+    /// A pattern type range start/end
+    PatTyRange,
 }
 
 impl DesugaringKind {
@@ -1190,6 +1192,7 @@ impl DesugaringKind {
             DesugaringKind::WhileLoop => "`while` loop",
             DesugaringKind::BoundModifier => "trait bound modifier",
             DesugaringKind::Contract => "contract check",
+            DesugaringKind::PatTyRange => "pattern type",
         }
     }
 }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 522bccb1acb..573c65a772c 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -308,6 +308,9 @@ symbols! {
         RangeFull,
         RangeInclusive,
         RangeInclusiveCopy,
+        RangeMax,
+        RangeMin,
+        RangeSub,
         RangeTo,
         RangeToInclusive,
         Rc,
@@ -1522,6 +1525,7 @@ symbols! {
         pattern_complexity_limit,
         pattern_parentheses,
         pattern_type,
+        pattern_type_range_trait,
         pattern_types,
         permissions_from_mode,
         phantom_data,
diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs
index bb21d84b09d..bc3923e4b4d 100644
--- a/compiler/rustc_symbol_mangling/src/v0.rs
+++ b/compiler/rustc_symbol_mangling/src/v0.rs
@@ -413,15 +413,8 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
             }
 
             ty::Pat(ty, pat) => match *pat {
-                ty::PatternKind::Range { start, end, include_end } => {
-                    let consts = [
-                        start,
-                        end,
-                        ty::Const::from_bool(
-                            self.tcx,
-                            matches!(include_end, rustc_hir::RangeEnd::Included),
-                        ),
-                    ];
+                ty::PatternKind::Range { start, end } => {
+                    let consts = [start, end];
                     // HACK: Represent as tuple until we have something better.
                     // HACK: constants are used in arrays, even if the types don't match.
                     self.push("T");
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 0fece96a3eb..54b6c22b2d8 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -708,7 +708,7 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
             ty::Pat(subty, pat) => {
                 self.require_sized(subty, ObligationCauseCode::Misc);
                 match *pat {
-                    ty::PatternKind::Range { start, end, include_end: _ } => {
+                    ty::PatternKind::Range { start, end } => {
                         let mut check = |c| {
                             let cause = self.cause(ObligationCauseCode::Misc);
                             self.out.push(traits::Obligation::with_depth(
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index e5f4a8b87bb..a53f0538c58 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -205,7 +205,7 @@ fn layout_of_uncached<'tcx>(
             let layout = cx.layout_of(ty)?.layout;
             let mut layout = LayoutData::clone(&layout.0);
             match *pat {
-                ty::PatternKind::Range { start, end, include_end } => {
+                ty::PatternKind::Range { start, end } => {
                     if let BackendRepr::Scalar(scalar) | BackendRepr::ScalarPair(scalar, _) =
                         &mut layout.backend_repr
                     {
@@ -213,14 +213,9 @@ fn layout_of_uncached<'tcx>(
                             .try_to_bits(tcx, cx.typing_env)
                             .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
 
-                        let mut end = extract_const_value(cx, ty, end)?
+                        scalar.valid_range_mut().end = extract_const_value(cx, ty, end)?
                             .try_to_bits(tcx, cx.typing_env)
                             .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
-                        match include_end {
-                            rustc_hir::RangeEnd::Included => {}
-                            rustc_hir::RangeEnd::Excluded => end = end.wrapping_sub(1),
-                        }
-                        scalar.valid_range_mut().end = end;
 
                         let niche = Niche {
                             offset: Size::ZERO,