Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add associated constant BITS to all integer types #76492

Merged
merged 4 commits into from
Sep 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions compiler/rustc_data_structures/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#![feature(generators)]
#![feature(generator_trait)]
#![feature(fn_traits)]
#![feature(int_bits_const)]
#![feature(min_specialization)]
#![feature(optin_builtin_traits)]
#![feature(nll)]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/src/tagged_ptr/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ where
P: Pointer,
T: Tag,
{
const TAG_BIT_SHIFT: usize = (8 * std::mem::size_of::<usize>()) - T::BITS;
const TAG_BIT_SHIFT: usize = usize::BITS as usize - T::BITS;
const ASSERTION: () = {
assert!(T::BITS <= P::BITS);
// Used for the transmute_copy's below
Expand Down
4 changes: 2 additions & 2 deletions library/alloc/src/collections/binary_heap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@

use core::fmt;
use core::iter::{FromIterator, FusedIterator, InPlaceIterable, SourceIter, TrustedLen};
use core::mem::{self, size_of, swap, ManuallyDrop};
use core::mem::{self, swap, ManuallyDrop};
use core::ops::{Deref, DerefMut};
use core::ptr;

Expand Down Expand Up @@ -617,7 +617,7 @@ impl<T: Ord> BinaryHeap<T> {

#[inline(always)]
fn log2_fast(x: usize) -> usize {
8 * size_of::<usize>() - (x.leading_zeros() as usize) - 1
(usize::BITS - x.leading_zeros() - 1) as usize
}

// `rebuild` takes O(len1 + len2) operations
Expand Down
1 change: 1 addition & 0 deletions library/alloc/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@
#![feature(fn_traits)]
#![feature(fundamental)]
#![feature(inplace_iteration)]
#![feature(int_bits_const)]
#![feature(lang_items)]
#![feature(layout_for_ptr)]
#![feature(libc)]
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/src/raw_vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ unsafe impl<#[may_dangle] T, A: AllocRef> Drop for RawVec<T, A> {

#[inline]
fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> {
if mem::size_of::<usize>() < 8 && alloc_size > isize::MAX as usize {
if usize::BITS < 64 && alloc_size > isize::MAX as usize {
Err(CapacityOverflow)
} else {
Ok(())
Expand Down
1 change: 1 addition & 0 deletions library/alloc/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#![feature(deque_range)]
#![feature(inplace_iteration)]
#![feature(iter_map_while)]
#![feature(int_bits_const)]

use std::collections::hash_map::DefaultHasher;
use std::hash::{Hash, Hasher};
Expand Down
5 changes: 2 additions & 3 deletions library/alloc/tests/string.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::borrow::Cow;
use std::collections::TryReserveError::*;
use std::mem::size_of;
use std::ops::Bound::*;

pub trait IntoCow<'a, B: ?Sized>
Expand Down Expand Up @@ -605,7 +604,7 @@ fn test_try_reserve() {
// on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
// Any platform that succeeds for these requests is technically broken with
// ptr::offset because LLVM is the worst.
let guards_against_isize = size_of::<usize>() < 8;
let guards_against_isize = usize::BITS < 64;

{
// Note: basic stuff is checked by test_reserve
Expand Down Expand Up @@ -686,7 +685,7 @@ fn test_try_reserve_exact() {
const MAX_CAP: usize = isize::MAX as usize;
const MAX_USIZE: usize = usize::MAX;

let guards_against_isize = size_of::<usize>() < 8;
let guards_against_isize = usize::BITS < 64;

{
let mut empty_string: String = String::new();
Expand Down
2 changes: 1 addition & 1 deletion library/alloc/tests/vec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1341,7 +1341,7 @@ fn test_try_reserve() {
// on 64-bit, we assume the OS will give an OOM for such a ridiculous size.
// Any platform that succeeds for these requests is technically broken with
// ptr::offset because LLVM is the worst.
let guards_against_isize = size_of::<usize>() < 8;
let guards_against_isize = usize::BITS < 64;

{
// Note: basic stuff is checked by test_reserve
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/fmt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2086,7 +2086,7 @@ impl<T: ?Sized> Pointer for *const T {
f.flags |= 1 << (FlagV1::SignAwareZeroPad as u32);

if f.width.is_none() {
f.width = Some(((mem::size_of::<usize>() * 8) / 4) + 2);
f.width = Some((usize::BITS / 4) as usize + 2);
}
}
f.flags |= 1 << (FlagV1::Alternate as u32);
Expand Down
34 changes: 9 additions & 25 deletions library/core/src/num/bignum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#![macro_use]

use crate::intrinsics;
use crate::mem;

/// Arithmetic operations required by bignums.
pub trait FullOps: Sized {
Expand Down Expand Up @@ -58,25 +57,22 @@ macro_rules! impl_full_ops {
// This cannot overflow;
// the output is between `0` and `2^nbits * (2^nbits - 1)`.
// FIXME: will LLVM optimize this into ADC or similar?
let nbits = mem::size_of::<$ty>() * 8;
let v = (self as $bigty) * (other as $bigty) + (carry as $bigty);
((v >> nbits) as $ty, v as $ty)
((v >> <$ty>::BITS) as $ty, v as $ty)
}

fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
// This cannot overflow;
// the output is between `0` and `2^nbits * (2^nbits - 1)`.
let nbits = mem::size_of::<$ty>() * 8;
let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
(carry as $bigty);
((v >> nbits) as $ty, v as $ty)
((v >> <$ty>::BITS) as $ty, v as $ty)
}

fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
debug_assert!(borrow < other);
// This cannot overflow; the output is between `0` and `other * (2^nbits - 1)`.
let nbits = mem::size_of::<$ty>() * 8;
let lhs = ((borrow as $bigty) << nbits) | (self as $bigty);
let lhs = ((borrow as $bigty) << <$ty>::BITS) | (self as $bigty);
let rhs = other as $bigty;
((lhs / rhs) as $ty, (lhs % rhs) as $ty)
}
Expand Down Expand Up @@ -128,13 +124,11 @@ macro_rules! define_bignum {

/// Makes a bignum from `u64` value.
pub fn from_u64(mut v: u64) -> $name {
use crate::mem;

let mut base = [0; $n];
let mut sz = 0;
while v > 0 {
base[sz] = v as $ty;
v >>= mem::size_of::<$ty>() * 8;
v >>= <$ty>::BITS;
sz += 1;
}
$name { size: sz, base: base }
Expand All @@ -150,9 +144,7 @@ macro_rules! define_bignum {
/// Returns the `i`-th bit where bit 0 is the least significant one.
/// In other words, the bit with weight `2^i`.
pub fn get_bit(&self, i: usize) -> u8 {
use crate::mem;

let digitbits = mem::size_of::<$ty>() * 8;
let digitbits = <$ty>::BITS as usize;
let d = i / digitbits;
let b = i % digitbits;
((self.base[d] >> b) & 1) as u8
Expand All @@ -166,8 +158,6 @@ macro_rules! define_bignum {
/// Returns the number of bits necessary to represent this value. Note that zero
/// is considered to need 0 bits.
pub fn bit_length(&self) -> usize {
use crate::mem;

// Skip over the most significant digits which are zero.
let digits = self.digits();
let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
Expand All @@ -180,7 +170,7 @@ macro_rules! define_bignum {
}
// This could be optimized with leading_zeros() and bit shifts, but that's
// probably not worth the hassle.
let digitbits = mem::size_of::<$ty>() * 8;
let digitbits = <$ty>::BITS as usize;
let mut i = nonzero.len() * digitbits - 1;
while self.get_bit(i) == 0 {
i -= 1;
Expand Down Expand Up @@ -265,9 +255,7 @@ macro_rules! define_bignum {

/// Multiplies itself by `2^bits` and returns its own mutable reference.
pub fn mul_pow2(&mut self, bits: usize) -> &mut $name {
use crate::mem;

let digitbits = mem::size_of::<$ty>() * 8;
let digitbits = <$ty>::BITS as usize;
let digits = bits / digitbits;
let bits = bits % digitbits;

Expand Down Expand Up @@ -393,13 +381,11 @@ macro_rules! define_bignum {
/// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
/// remainder.
pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) {
use crate::mem;

// Stupid slow base-2 long division taken from
// https://en.wikipedia.org/wiki/Division_algorithm
// FIXME use a greater base ($ty) for the long division.
assert!(!d.is_zero());
let digitbits = mem::size_of::<$ty>() * 8;
let digitbits = <$ty>::BITS as usize;
for digit in &mut q.base[..] {
*digit = 0;
}
Expand Down Expand Up @@ -462,10 +448,8 @@ macro_rules! define_bignum {

impl crate::fmt::Debug for $name {
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
use crate::mem;

let sz = if self.size < 1 { 1 } else { self.size };
let digitlen = mem::size_of::<$ty>() * 2;
let digitlen = <$ty>::BITS as usize / 4;

write!(f, "{:#x}", self.base[sz - 1])?;
for &v in self.base[..sz - 1].iter().rev() {
Expand Down
28 changes: 28 additions & 0 deletions library/core/src/num/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,20 @@ $EndFeature, "
pub const MAX: Self = !Self::MIN;
}

doc_comment! {
concat!("The size of this integer type in bits.

# Examples

```
", $Feature, "#![feature(int_bits_const)]
assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");",
$EndFeature, "
```"),
#[unstable(feature = "int_bits_const", issue = "76904")]
pub const BITS: u32 = $BITS;
}

doc_comment! {
concat!("Converts a string slice in a given base to an integer.

Expand Down Expand Up @@ -2601,6 +2615,20 @@ $EndFeature, "
pub const MAX: Self = !0;
}

doc_comment! {
concat!("The size of this integer type in bits.

# Examples

```
", $Feature, "#![feature(int_bits_const)]
assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");",
$EndFeature, "
```"),
#[unstable(feature = "int_bits_const", issue = "76904")]
pub const BITS: u32 = $BITS;
}

doc_comment! {
concat!("Converts a string slice in a given base to an integer.

Expand Down
6 changes: 3 additions & 3 deletions library/core/src/slice/sort.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ fn break_patterns<T>(v: &mut [T]) {
random
};
let mut gen_usize = || {
if mem::size_of::<usize>() <= 4 {
if usize::BITS <= 32 {
gen_u32() as usize
} else {
(((gen_u32() as u64) << 32) | (gen_u32() as u64)) as usize
Expand Down Expand Up @@ -667,7 +667,7 @@ where
///
/// `limit` is the number of allowed imbalanced partitions before switching to `heapsort`. If zero,
/// this function will immediately switch to heapsort.
fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: usize)
fn recurse<'a, T, F>(mut v: &'a mut [T], is_less: &mut F, mut pred: Option<&'a T>, mut limit: u32)
where
F: FnMut(&T, &T) -> bool,
{
Expand Down Expand Up @@ -763,7 +763,7 @@ where
}

// Limit the number of imbalanced partitions to `floor(log2(len)) + 1`.
let limit = mem::size_of::<usize>() * 8 - v.len().leading_zeros() as usize;
let limit = usize::BITS - v.len().leading_zeros();

recurse(v, &mut is_less, None, limit);
}
Expand Down
2 changes: 1 addition & 1 deletion library/core/tests/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ fn test_iterator_step_by_nth_overflow() {
}

let mut it = Test(0);
let root = usize::MAX >> (::std::mem::size_of::<usize>() * 8 / 2);
let root = usize::MAX >> (usize::BITS / 2);
let n = root + 20;
(&mut it).step_by(n).nth(n);
assert_eq!(it.0, n as Bigger * n as Bigger);
Expand Down
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
#![feature(partition_point)]
#![feature(once_cell)]
#![feature(unsafe_block_in_unsafe_fn)]
#![feature(int_bits_const)]
#![deny(unsafe_op_in_unsafe_fn)]

extern crate test;
Expand Down
20 changes: 8 additions & 12 deletions library/core/tests/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ macro_rules! int_module {
($T:ident, $T_i:ident) => {
#[cfg(test)]
mod tests {
use core::mem;
use core::ops::{BitAnd, BitOr, BitXor, Not, Shl, Shr};
use core::$T_i::*;

Expand Down Expand Up @@ -82,30 +81,27 @@ macro_rules! int_module {

#[test]
fn test_count_zeros() {
let bits = mem::size_of::<$T>() * 8;
assert_eq!(A.count_zeros(), bits as u32 - 3);
assert_eq!(B.count_zeros(), bits as u32 - 2);
assert_eq!(C.count_zeros(), bits as u32 - 5);
assert_eq!(A.count_zeros(), $T::BITS - 3);
assert_eq!(B.count_zeros(), $T::BITS - 2);
assert_eq!(C.count_zeros(), $T::BITS - 5);
}

#[test]
fn test_leading_trailing_ones() {
let bits = (mem::size_of::<$T>() * 8) as u32;

let a: $T = 0b0101_1111;
assert_eq!(a.trailing_ones(), 5);
assert_eq!((!a).leading_ones(), bits - 7);
assert_eq!((!a).leading_ones(), $T::BITS - 7);

assert_eq!(a.reverse_bits().leading_ones(), 5);

assert_eq!(_1.leading_ones(), bits);
assert_eq!(_1.trailing_ones(), bits);
assert_eq!(_1.leading_ones(), $T::BITS);
assert_eq!(_1.trailing_ones(), $T::BITS);

assert_eq!((_1 << 1).trailing_ones(), 0);
assert_eq!(MAX.leading_ones(), 0);

assert_eq!((_1 << 1).leading_ones(), bits - 1);
assert_eq!(MAX.trailing_ones(), bits - 1);
assert_eq!((_1 << 1).leading_ones(), $T::BITS - 1);
assert_eq!(MAX.trailing_ones(), $T::BITS - 1);

assert_eq!(_0.leading_ones(), 0);
assert_eq!(_0.trailing_ones(), 0);
Expand Down
Loading