Skip to content

Commit

Permalink
Require literals for some (u)int_impl! parameters
Browse files Browse the repository at this point in the history
The point of these is to be seen lexically in the docs, so they should always be passed as the correct literal, not as an expression.

(Otherwise we could just compute `Min`/`Max` from `BITS`, for example.)
  • Loading branch information
scottmcm committed Feb 23, 2023
1 parent f715e43 commit 5c7ae25
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 36 deletions.
45 changes: 25 additions & 20 deletions library/core/src/num/int_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@ macro_rules! int_impl {
Self = $SelfT:ty,
ActualT = $ActualT:ident,
UnsignedT = $UnsignedT:ty,
BITS = $BITS:expr,
BITS_MINUS_ONE = $BITS_MINUS_ONE:expr,
Min = $Min:expr,
Max = $Max:expr,
rot = $rot:expr,
rot_op = $rot_op:expr,
rot_result = $rot_result:expr,
swap_op = $swap_op:expr,
swapped = $swapped:expr,
reversed = $reversed:expr,
le_bytes = $le_bytes:expr,
be_bytes = $be_bytes:expr,

// There are all for use *only* in doc comments.
// As such, they're all passed as literals -- passing them as a string
// literal is fine if they need to be multiple code tokens.
// In non-comments, use the associated constants rather than these.
BITS = $BITS:literal,
BITS_MINUS_ONE = $BITS_MINUS_ONE:literal,
Min = $Min:literal,
Max = $Max:literal,
rot = $rot:literal,
rot_op = $rot_op:literal,
rot_result = $rot_result:literal,
swap_op = $swap_op:literal,
swapped = $swapped:literal,
reversed = $reversed:literal,
le_bytes = $le_bytes:literal,
be_bytes = $be_bytes:literal,
to_xe_bytes_doc = $to_xe_bytes_doc:expr,
from_xe_bytes_doc = $from_xe_bytes_doc:expr,
bound_condition = $bound_condition:expr,
bound_condition = $bound_condition:literal,
) => {
/// The smallest value that can be represented by this integer type
#[doc = concat!("(&minus;2<sup>", $BITS_MINUS_ONE, "</sup>", $bound_condition, ").")]
Expand All @@ -30,7 +35,7 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN, ", stringify!($Min), ");")]
/// ```
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MIN: Self = !0 ^ ((!0 as $UnsignedT) >> 1) as Self;
pub const MIN: Self = !Self::MAX;

/// The largest value that can be represented by this integer type
#[doc = concat!("(2<sup>", $BITS_MINUS_ONE, "</sup> &minus; 1", $bound_condition, ").")]
Expand All @@ -43,7 +48,7 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX, ", stringify!($Max), ");")]
/// ```
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
pub const MAX: Self = !Self::MIN;
pub const MAX: Self = (<$UnsignedT>::MAX >> 1) as Self;

/// The size of this integer type in bits.
///
Expand All @@ -53,7 +58,7 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ```
#[stable(feature = "int_bits_const", since = "1.53.0")]
pub const BITS: u32 = $BITS;
pub const BITS: u32 = <$UnsignedT>::BITS;

/// Converts a string slice in a given base to an integer.
///
Expand Down Expand Up @@ -1380,7 +1385,7 @@ macro_rules! int_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
self.unchecked_shl(rhs & ($BITS - 1))
self.unchecked_shl(rhs & (Self::BITS - 1))
}
}

Expand Down Expand Up @@ -1410,7 +1415,7 @@ macro_rules! int_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
self.unchecked_shr(rhs & ($BITS - 1))
self.unchecked_shr(rhs & (Self::BITS - 1))
}
}

Expand Down Expand Up @@ -1916,7 +1921,7 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
(self.wrapping_shl(rhs), rhs >= Self::BITS)
}

/// Shifts self right by `rhs` bits.
Expand All @@ -1939,7 +1944,7 @@ macro_rules! int_impl {
without modifying the original"]
#[inline]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
(self.wrapping_shr(rhs), rhs >= Self::BITS)
}

/// Computes the absolute value of `self`.
Expand Down
37 changes: 21 additions & 16 deletions library/core/src/num/uint_macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,24 @@ macro_rules! uint_impl {
ActualT = $ActualT:ident,
SignedT = $SignedT:ident,
NonZeroT = $NonZeroT:ident,
BITS = $BITS:expr,
MAX = $MaxV:expr,
rot = $rot:expr,
rot_op = $rot_op:expr,
rot_result = $rot_result:expr,
swap_op = $swap_op:expr,
swapped = $swapped:expr,
reversed = $reversed:expr,
le_bytes = $le_bytes:expr,
be_bytes = $be_bytes:expr,

// There are all for use *only* in doc comments.
// As such, they're all passed as literals -- passing them as a string
// literal is fine if they need to be multiple code tokens.
// In non-comments, use the associated constants rather than these.
BITS = $BITS:literal,
MAX = $MaxV:literal,
rot = $rot:literal,
rot_op = $rot_op:literal,
rot_result = $rot_result:literal,
swap_op = $swap_op:literal,
swapped = $swapped:literal,
reversed = $reversed:literal,
le_bytes = $le_bytes:literal,
be_bytes = $be_bytes:literal,
to_xe_bytes_doc = $to_xe_bytes_doc:expr,
from_xe_bytes_doc = $from_xe_bytes_doc:expr,
bound_condition = $bound_condition:expr,
bound_condition = $bound_condition:literal,
) => {
/// The smallest value that can be represented by this integer type.
///
Expand Down Expand Up @@ -51,7 +56,7 @@ macro_rules! uint_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::BITS, ", stringify!($BITS), ");")]
/// ```
#[stable(feature = "int_bits_const", since = "1.53.0")]
pub const BITS: u32 = $BITS;
pub const BITS: u32 = Self::MAX.count_ones();

/// Converts a string slice in a given base to an integer.
///
Expand Down Expand Up @@ -1403,7 +1408,7 @@ macro_rules! uint_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
self.unchecked_shl(rhs & ($BITS - 1))
self.unchecked_shl(rhs & (Self::BITS - 1))
}
}

Expand Down Expand Up @@ -1436,7 +1441,7 @@ macro_rules! uint_impl {
// SAFETY: the masking by the bitsize of the type ensures that we do not shift
// out of bounds
unsafe {
self.unchecked_shr(rhs & ($BITS - 1))
self.unchecked_shr(rhs & (Self::BITS - 1))
}
}

Expand Down Expand Up @@ -1860,7 +1865,7 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline(always)]
pub const fn overflowing_shl(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shl(rhs), (rhs > ($BITS - 1)))
(self.wrapping_shl(rhs), rhs >= Self::BITS)
}

/// Shifts self right by `rhs` bits.
Expand All @@ -1885,7 +1890,7 @@ macro_rules! uint_impl {
without modifying the original"]
#[inline(always)]
pub const fn overflowing_shr(self, rhs: u32) -> (Self, bool) {
(self.wrapping_shr(rhs), (rhs > ($BITS - 1)))
(self.wrapping_shr(rhs), rhs >= Self::BITS)
}

/// Raises self to the power of `exp`, using exponentiation by squaring.
Expand Down

0 comments on commit 5c7ae25

Please sign in to comment.