about summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis
diff options
context:
space:
mode:
authorNadrieril <nadrieril+git@gmail.com>2023-12-11 11:10:19 +0100
committerNadrieril <nadrieril+git@gmail.com>2023-12-11 11:20:55 +0100
commitde3f983bcdafcf9ba1bd322661f85e3ab1d50e15 (patch)
treeddb3a05fee9fd3f0101b9e055534608331dcb599 /compiler/rustc_pattern_analysis
parent24adca0a26c3470cc0feabb19a77eb4e2e7b8278 (diff)
downloadrust-de3f983bcdafcf9ba1bd322661f85e3ab1d50e15.tar.gz
rust-de3f983bcdafcf9ba1bd322661f85e3ab1d50e15.zip
Make `MaybeInfiniteInt` rustc-independent
Diffstat (limited to 'compiler/rustc_pattern_analysis')
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs44
-rw-r--r--compiler/rustc_pattern_analysis/src/cx.rs49
2 files changed, 59 insertions, 34 deletions
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index aa02ca27add..16438ae574d 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -159,9 +159,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::RangeEnd;
 use rustc_index::IndexVec;
 use rustc_middle::mir::Const;
-use rustc_middle::ty::layout::IntegerExt;
-use rustc_middle::ty::{self, Ty, TyCtxt};
-use rustc_target::abi::{Integer, VariantIdx};
+use rustc_target::abi::VariantIdx;
 
 use self::Constructor::*;
 use self::MaybeInfiniteInt::*;
@@ -183,6 +181,7 @@ enum Presence {
 pub enum MaybeInfiniteInt {
     NegInfinity,
     /// Encoded value. DO NOT CONSTRUCT BY HAND; use `new_finite`.
+    #[non_exhaustive]
     Finite(u128),
     /// The integer after `u128::MAX`. We need it to represent `x..=u128::MAX` as an exclusive range.
     JustAfterMax,
@@ -190,23 +189,31 @@ pub enum MaybeInfiniteInt {
 }
 
 impl MaybeInfiniteInt {
-    // The return value of `signed_bias` should be XORed with a value to encode/decode it.
-    pub(crate) fn signed_bias(tcx: TyCtxt<'_>, ty: Ty<'_>) -> u128 {
-        match *ty.kind() {
-            ty::Int(ity) => {
-                let bits = Integer::from_int_ty(&tcx, ity).size().bits() as u128;
-                1u128 << (bits - 1)
-            }
-            _ => 0,
-        }
+    pub fn new_finite_uint(bits: u128) -> Self {
+        Finite(bits)
     }
-
-    pub fn new_finite(tcx: TyCtxt<'_>, ty: Ty<'_>, bits: u128) -> Self {
-        let bias = Self::signed_bias(tcx, ty);
+    pub fn new_finite_int(bits: u128, size: u64) -> Self {
         // Perform a shift if the underlying types are signed, which makes the interval arithmetic
         // type-independent.
-        let x = bits ^ bias;
-        Finite(x)
+        let bias = 1u128 << (size - 1);
+        Finite(bits ^ bias)
+    }
+
+    pub fn as_finite_uint(self) -> Option<u128> {
+        match self {
+            Finite(bits) => Some(bits),
+            _ => None,
+        }
+    }
+    pub fn as_finite_int(self, size: u64) -> Option<u128> {
+        // We decode the shift.
+        match self {
+            Finite(bits) => {
+                let bias = 1u128 << (size - 1);
+                Some(bits ^ bias)
+            }
+            _ => None,
+        }
     }
 
     /// Note: this will not turn a finite value into an infinite one or vice-versa.
@@ -253,8 +260,7 @@ impl IntRange {
     }
 
     #[inline]
-    pub fn from_bits<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, bits: u128) -> IntRange {
-        let x = MaybeInfiniteInt::new_finite(tcx, ty, bits);
+    pub fn from_singleton(x: MaybeInfiniteInt) -> IntRange {
         IntRange { lo: x, hi: x.plus_one() }
     }
 
diff --git a/compiler/rustc_pattern_analysis/src/cx.rs b/compiler/rustc_pattern_analysis/src/cx.rs
index ffcbd2f5d83..8a4f39a1f4a 100644
--- a/compiler/rustc_pattern_analysis/src/cx.rs
+++ b/compiler/rustc_pattern_analysis/src/cx.rs
@@ -204,10 +204,10 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
     #[instrument(level = "debug", skip(self), ret)]
     pub fn ctors_for_ty(&self, ty: Ty<'tcx>) -> ConstructorSet {
         let cx = self;
-        let make_range = |start, end| {
+        let make_uint_range = |start, end| {
             IntRange::from_range(
-                MaybeInfiniteInt::new_finite(cx.tcx, ty, start),
-                MaybeInfiniteInt::new_finite(cx.tcx, ty, end),
+                MaybeInfiniteInt::new_finite_uint(start),
+                MaybeInfiniteInt::new_finite_uint(end),
                 RangeEnd::Included,
             )
         };
@@ -218,8 +218,8 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
             ty::Char => {
                 // The valid Unicode Scalar Value ranges.
                 ConstructorSet::Integers {
-                    range_1: make_range('\u{0000}' as u128, '\u{D7FF}' as u128),
-                    range_2: Some(make_range('\u{E000}' as u128, '\u{10FFFF}' as u128)),
+                    range_1: make_uint_range('\u{0000}' as u128, '\u{D7FF}' as u128),
+                    range_2: Some(make_uint_range('\u{E000}' as u128, '\u{10FFFF}' as u128)),
                 }
             }
             &ty::Int(ity) => {
@@ -230,22 +230,24 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
                         hi: MaybeInfiniteInt::PosInfinity,
                     }
                 } else {
-                    let bits = Integer::from_int_ty(&cx.tcx, ity).size().bits() as u128;
-                    let min = 1u128 << (bits - 1);
+                    let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
+                    let min = 1u128 << (size - 1);
                     let max = min - 1;
-                    make_range(min, max)
+                    let min = MaybeInfiniteInt::new_finite_int(min, size);
+                    let max = MaybeInfiniteInt::new_finite_int(max, size);
+                    IntRange::from_range(min, max, RangeEnd::Included)
                 };
                 ConstructorSet::Integers { range_1: range, range_2: None }
             }
             &ty::Uint(uty) => {
                 let range = if ty.is_ptr_sized_integral() {
                     // The max value of `usize` is not allowed to be observed.
-                    let lo = MaybeInfiniteInt::new_finite(cx.tcx, ty, 0);
+                    let lo = MaybeInfiniteInt::new_finite_uint(0);
                     IntRange { lo, hi: MaybeInfiniteInt::PosInfinity }
                 } else {
                     let size = Integer::from_uint_ty(&cx.tcx, uty).size();
                     let max = size.truncate(u128::MAX);
-                    make_range(0, max)
+                    make_uint_range(0, max)
                 };
                 ConstructorSet::Integers { range_1: range, range_2: None }
             }
@@ -329,7 +331,13 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
             PatRangeBoundary::NegInfinity => MaybeInfiniteInt::NegInfinity,
             PatRangeBoundary::Finite(value) => {
                 let bits = value.eval_bits(self.tcx, self.param_env);
-                MaybeInfiniteInt::new_finite(self.tcx, ty, bits)
+                match *ty.kind() {
+                    ty::Int(ity) => {
+                        let size = Integer::from_int_ty(&self.tcx, ity).size().bits();
+                        MaybeInfiniteInt::new_finite_int(bits, size)
+                    }
+                    _ => MaybeInfiniteInt::new_finite_uint(bits),
+                }
             }
             PatRangeBoundary::PosInfinity => MaybeInfiniteInt::PosInfinity,
         }
@@ -428,7 +436,16 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
                     }
                     ty::Char | ty::Int(_) | ty::Uint(_) => {
                         ctor = match value.try_eval_bits(cx.tcx, cx.param_env) {
-                            Some(bits) => IntRange(IntRange::from_bits(cx.tcx, pat.ty, bits)),
+                            Some(bits) => {
+                                let x = match *pat.ty.kind() {
+                                    ty::Int(ity) => {
+                                        let size = Integer::from_int_ty(&cx.tcx, ity).size().bits();
+                                        MaybeInfiniteInt::new_finite_int(bits, size)
+                                    }
+                                    _ => MaybeInfiniteInt::new_finite_uint(bits),
+                                };
+                                IntRange(IntRange::from_singleton(x))
+                            }
                             None => Opaque(OpaqueId::new()),
                         };
                         fields = &[];
@@ -559,10 +576,12 @@ impl<'p, 'tcx> MatchCheckCtxt<'p, 'tcx> {
         let tcx = self.tcx;
         match miint {
             NegInfinity => PatRangeBoundary::NegInfinity,
-            Finite(x) => {
-                let bias = MaybeInfiniteInt::signed_bias(tcx, ty);
-                let bits = x ^ bias;
+            Finite(_) => {
                 let size = ty.primitive_size(tcx);
+                let bits = match *ty.kind() {
+                    ty::Int(_) => miint.as_finite_int(size.bits()).unwrap(),
+                    _ => miint.as_finite_uint().unwrap(),
+                };
                 match Scalar::try_from_uint(bits, size) {
                     Some(scalar) => {
                         let value = mir::Const::from_scalar(tcx, scalar, ty);