about summary refs log tree commit diff
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2024-04-18 08:44:17 +0200
committerRalf Jung <post@ralfj.de>2024-04-19 17:17:31 +0200
commitd3f927db874aaa82480cd2120e15a507e7cb9b15 (patch)
tree977480a87bf4289cef9c3d652147b47e342bf2be
parent42220f0930a0fb187a75edeeee91d525c326f56d (diff)
downloadrust-d3f927db874aaa82480cd2120e15a507e7cb9b15.tar.gz
rust-d3f927db874aaa82480cd2120e15a507e7cb9b15.zip
avoid PartialOrd on ScalarInt
we don't know their sign so we cannot, in general, order them properly
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs14
-rw-r--r--compiler/rustc_middle/src/thir.rs19
-rw-r--r--compiler/rustc_middle/src/ty/consts/int.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts/valtree.rs2
4 files changed, 24 insertions, 13 deletions
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 0af012e90cb..b788cfde85e 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -244,6 +244,8 @@ impl<'tcx> Const<'tcx> {
             Const::Ty(c) => match c.kind() {
                 ty::ConstKind::Value(valtree) if c.ty().is_primitive() => {
                     // A valtree of a type where leaves directly represent the scalar const value.
+                    // Just checking whether it is a leaf is insufficient as e.g. references are leafs
+                    // but the leaf value is the value they point to, not the reference itself!
                     Some(valtree.unwrap_leaf().into())
                 }
                 _ => None,
@@ -255,7 +257,17 @@ impl<'tcx> Const<'tcx> {
 
     #[inline]
     pub fn try_to_scalar_int(self) -> Option<ScalarInt> {
-        self.try_to_scalar()?.try_to_int().ok()
+        // This is equivalent to `self.try_to_scalar()?.try_to_int().ok()`, but measurably faster.
+        match self {
+            Const::Val(ConstValue::Scalar(Scalar::Int(x)), _) => Some(x),
+            Const::Ty(c) => match c.kind() {
+                ty::ConstKind::Value(valtree) if c.ty().is_primitive() => {
+                    Some(valtree.unwrap_leaf())
+                }
+                _ => None,
+            },
+            _ => None,
+        }
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 8763e94c8b0..d4573c9776c 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -16,7 +16,7 @@ use rustc_hir::{BindingAnnotation, ByRef, HirId, MatchSource, RangeEnd};
 use rustc_index::newtype_index;
 use rustc_index::IndexVec;
 use rustc_middle::middle::region;
-use rustc_middle::mir::interpret::{AllocId, Scalar};
+use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, UnOp};
 use rustc_middle::ty::adjustment::PointerCoercion;
 use rustc_middle::ty::layout::IntegerExt;
@@ -1009,18 +1009,17 @@ impl<'tcx> PatRangeBoundary<'tcx> {
 
             // This code is hot when compiling matches with many ranges. So we
             // special-case extraction of evaluated scalars for speed, for types where
-            // raw data comparisons are appropriate. E.g. `unicode-normalization` has
+            // unsigned int comparisons are appropriate. E.g. `unicode-normalization` has
             // many ranges such as '\u{037A}'..='\u{037F}', and chars can be compared
             // in this way.
-            (Finite(mir::Const::Ty(a)), Finite(mir::Const::Ty(b)))
-                if matches!(ty.kind(), ty::Uint(_) | ty::Char) =>
-            {
-                return Some(a.to_valtree().cmp(&b.to_valtree()));
+            (Finite(a), Finite(b)) if matches!(ty.kind(), ty::Uint(_) | ty::Char) => {
+                if let (Some(a), Some(b)) = (a.try_to_scalar_int(), b.try_to_scalar_int()) {
+                    let sz = ty.primitive_size(tcx);
+                    let a = a.assert_uint(sz);
+                    let b = b.assert_uint(sz);
+                    return Some(a.cmp(&b));
+                }
             }
-            (
-                Finite(mir::Const::Val(mir::ConstValue::Scalar(Scalar::Int(a)), _)),
-                Finite(mir::Const::Val(mir::ConstValue::Scalar(Scalar::Int(b)), _)),
-            ) if matches!(ty.kind(), ty::Uint(_) | ty::Char) => return Some(a.cmp(&b)),
             _ => {}
         }
 
diff --git a/compiler/rustc_middle/src/ty/consts/int.rs b/compiler/rustc_middle/src/ty/consts/int.rs
index 2bf2341cbc4..40ac87873a0 100644
--- a/compiler/rustc_middle/src/ty/consts/int.rs
+++ b/compiler/rustc_middle/src/ty/consts/int.rs
@@ -126,7 +126,7 @@ impl IntoDiagArg for ConstInt {
 ///
 /// This is a packed struct in order to allow this type to be optimally embedded in enums
 /// (like Scalar).
-#[derive(Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
+#[derive(Clone, Copy, Eq, PartialEq, Hash)]
 #[repr(packed)]
 pub struct ScalarInt {
     /// The first `size` bytes of `data` are the value.
diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs
index ffa0e89c473..96bc5515a56 100644
--- a/compiler/rustc_middle/src/ty/consts/valtree.rs
+++ b/compiler/rustc_middle/src/ty/consts/valtree.rs
@@ -3,7 +3,7 @@ use crate::mir::interpret::Scalar;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_macros::{HashStable, TyDecodable, TyEncodable};
 
-#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)]
+#[derive(Copy, Clone, Debug, Hash, TyEncodable, TyDecodable, Eq, PartialEq)]
 #[derive(HashStable)]
 /// This datastructure is used to represent the value of constants used in the type system.
 ///