about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-03-31 10:33:56 +0000
committerbors <bors@rust-lang.org>2022-03-31 10:33:56 +0000
commitdf20355fa9fa5e9fb89be4e4bfee8a643bb7a23e (patch)
tree0524050d132dafc2ce53626125011a0287ea3699
parente730969b0d433d66d4f1c0bbd9ff70050c274ad5 (diff)
parent2799885ed03708eea1ec372339317bd97e5c5601 (diff)
downloadrust-df20355fa9fa5e9fb89be4e4bfee8a643bb7a23e.tar.gz
rust-df20355fa9fa5e9fb89be4e4bfee8a643bb7a23e.zip
Auto merge of #95456 - RalfJung:size, r=oli-obk
allow large Size again

This basically reverts most of https://github.com/rust-lang/rust/pull/80042, and instead does the panic in `bits()` with a `#[cold]` function to make sure it does not get inlined.

https://github.com/rust-lang/rust/pull/80042 added a comment about an invariant ("The top 3 bits are ALWAYS zero") that is not actually enforced, and if it were enforced that would be a problem for https://github.com/rust-lang/rust/pull/95388. So I think we should not have that invariant, and I adjusted the code accordingly.

r? `@oli-obk` Cc `@sivadeilra`
-rw-r--r--compiler/rustc_target/src/abi/mod.rs23
1 files changed, 7 insertions, 16 deletions
diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs
index 6082cdb78e4..52fce7c0553 100644
--- a/compiler/rustc_target/src/abi/mod.rs
+++ b/compiler/rustc_target/src/abi/mod.rs
@@ -279,7 +279,6 @@ impl ToJson for Endian {
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Encodable, Decodable)]
 #[derive(HashStable_Generic)]
 pub struct Size {
-    // The top 3 bits are ALWAYS zero.
     raw: u64,
 }
 
@@ -287,22 +286,9 @@ impl Size {
     pub const ZERO: Size = Size { raw: 0 };
 
     /// Rounds `bits` up to the next-higher byte boundary, if `bits` is
-    /// is not aligned.
+    /// not a multiple of 8.
     pub fn from_bits(bits: impl TryInto<u64>) -> Size {
         let bits = bits.try_into().ok().unwrap();
-
-        #[cold]
-        fn overflow(bits: u64) -> ! {
-            panic!("Size::from_bits({}) has overflowed", bits);
-        }
-
-        // This is the largest value of `bits` that does not cause overflow
-        // during rounding, and guarantees that the resulting number of bytes
-        // cannot cause overflow when multiplied by 8.
-        if bits > 0xffff_ffff_ffff_fff8 {
-            overflow(bits);
-        }
-
         // Avoid potential overflow from `bits + 7`.
         Size { raw: bits / 8 + ((bits % 8) + 7) / 8 }
     }
@@ -325,7 +311,12 @@ impl Size {
 
     #[inline]
     pub fn bits(self) -> u64 {
-        self.raw << 3
+        #[cold]
+        fn overflow(bytes: u64) -> ! {
+            panic!("Size::bits: {} bytes in bits doesn't fit in u64", bytes)
+        }
+
+        self.bytes().checked_mul(8).unwrap_or_else(|| overflow(self.bytes()))
     }
 
     #[inline]