Rollup merge of #80959 - jhpratt:unsigned_abs-stabilization, r=m-ou-se

Stabilize `unsigned_abs`

Resolves #74913.

This PR stabilizes the `i*::unsigned_abs()` method, which returns the absolute value of an integer _as its unsigned equivalent_. This has the advantage that it does not overflow on `i*::MIN`.

I have gone ahead and used this in a couple locations throughout the repository.
This commit is contained in:
Yuki Okushi 2021-01-30 13:36:44 +09:00 committed by GitHub
commit 91ea1cbc17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 8 additions and 17 deletions

View File

@ -588,12 +588,3 @@ pub fn read_target_uint(endianness: Endian, mut source: &[u8]) -> Result<u128, i
debug_assert!(source.len() == 0); // We should have consumed the source buffer.
uint
}
/// Computes the unsigned absolute value without wrapping or panicking.
#[inline]
pub fn uabs(value: i64) -> u64 {
// The only tricky part here is if value == i64::MIN. In that case,
// wrapping_abs() returns i64::MIN == -2^63. Casting this value to a u64
// gives 2^63, the correct value.
value.wrapping_abs() as u64
}

View File

@ -1,4 +1,4 @@
use super::{uabs, AllocId, InterpResult};
use super::{AllocId, InterpResult};
use rustc_macros::HashStable;
use rustc_target::abi::{HasDataLayout, Size};
@ -57,7 +57,7 @@ pub trait PointerArithmetic: HasDataLayout {
#[inline]
fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) {
// We need to make sure that i fits in a machine isize.
let n = uabs(i);
let n = i.unsigned_abs();
if i >= 0 {
let (val, over) = self.overflowing_offset(val, n);
(val, over || i > self.machine_isize_max())

View File

@ -7,7 +7,7 @@ use std::convert::TryFrom;
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{
self,
interpret::{uabs, ConstValue, GlobalId, InterpResult, Scalar},
interpret::{ConstValue, GlobalId, InterpResult, Scalar},
BinOp,
};
use rustc_middle::ty;
@ -542,7 +542,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
// memory between these pointers must be accessible. Note that we do not require the
// pointers to be properly aligned (unlike a read/write operation).
let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr };
let size: u64 = uabs(offset_bytes);
let size = offset_bytes.unsigned_abs();
// This call handles checking for integer/NULL pointers.
self.memory.check_ptr_access_align(
min_ptr,

View File

@ -530,7 +530,7 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
if val < 0 {
neg = true;
}
Some(val.wrapping_abs() as u128)
Some(val.unsigned_abs())
})
}
_ => {

View File

@ -332,7 +332,7 @@ fn bound_intermediate_digits(decimal: &Decimal<'_>, e: i64) -> u64 {
// It tries to find a positive number k such that `f << k / 10^e` is an in-range
// significand. This will result in about `2^53 * f * 10^e` < `10^17 * f * 10^e`.
// One input that triggers this is 0.33...33 (375 x 3).
f_len + (e.abs() as u64) + 17
f_len + e.unsigned_abs() + 17
}
}

View File

@ -1158,12 +1158,12 @@ macro_rules! int_impl {
/// Basic usage:
///
/// ```
/// #![feature(unsigned_abs)]
#[doc = concat!("assert_eq!(100", stringify!($SelfT), ".unsigned_abs(), 100", stringify!($UnsignedT), ");")]
#[doc = concat!("assert_eq!((-100", stringify!($SelfT), ").unsigned_abs(), 100", stringify!($UnsignedT), ");")]
/// assert_eq!((-128i8).unsigned_abs(), 128u8);
/// ```
#[unstable(feature = "unsigned_abs", issue = "74913")]
#[stable(feature = "unsigned_abs", since = "1.51.0")]
#[rustc_const_stable(feature = "unsigned_abs", since = "1.51.0")]
#[inline]
pub const fn unsigned_abs(self) -> $UnsignedT {
self.wrapping_abs() as $UnsignedT