Auto merge of #133026 - workingjubilee:rollup-q8ig6ah, r=workingjubilee
Rollup of 7 pull requests Successful merges: - #131304 (float types: move copysign, abs, signum to libcore) - #132907 (Change intrinsic declarations to new style) - #132971 (Handle infer vars in anon consts on stable) - #133003 (Make `CloneToUninit` dyn-compatible) - #133004 (btree: simplify the backdoor between set and map) - #133008 (update outdated comment about test-float-parse) - #133012 (Add test cases for #125918) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
dae7ac133b
33 changed files with 1910 additions and 1321 deletions
|
@ -325,6 +325,9 @@ impl<'tcx> Const<'tcx> {
|
|||
|
||||
match c.kind() {
|
||||
ConstKind::Value(ty, val) => Ok(tcx.valtree_to_const_val((ty, val))),
|
||||
ConstKind::Expr(_) => {
|
||||
bug!("Normalization of `ty::ConstKind::Expr` is unimplemented")
|
||||
}
|
||||
_ => Err(tcx.dcx().delayed_bug("Unevaluated `ty::Const` in MIR body").into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -578,16 +578,28 @@ pub fn try_evaluate_const<'tcx>(
|
|||
(args, param_env)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// FIXME: We don't check anything on stable as the only way we can wind up with
|
||||
// an unevaluated constant containing generic parameters is through array repeat
|
||||
// expression counts which have a future compat lint for usage of generic parameters
|
||||
// instead of a hard error.
|
||||
} else if tcx.def_kind(uv.def) == DefKind::AnonConst && uv.has_non_region_infer() {
|
||||
// FIXME: remove this when `const_evaluatable_unchecked` is a hard error.
|
||||
//
|
||||
// This codepath is however also reachable by `generic_const_exprs` and some other
|
||||
// feature gates which allow constants in the type system to use generic parameters.
|
||||
// In theory we should be checking for generic parameters here and returning an error
|
||||
// in such cases.
|
||||
// Diagnostics will sometimes replace the identity args of anon consts in
|
||||
// array repeat expr counts with inference variables so we have to handle this
|
||||
// even though it is not something we should ever actually encounter.
|
||||
//
|
||||
// Array repeat expr counts are allowed to syntactically use generic parameters
|
||||
// but must not actually depend on them in order to evalaute succesfully. This means
|
||||
// that it is actually fine to evalaute them in their own environment rather than with
|
||||
// the actually provided generic arguments.
|
||||
tcx.dcx().delayed_bug(
|
||||
"Encountered anon const with inference variable args but no error reported",
|
||||
);
|
||||
|
||||
let args = GenericArgs::identity_for_item(tcx, uv.def);
|
||||
let param_env = tcx.param_env(uv.def);
|
||||
(args, param_env)
|
||||
} else {
|
||||
// FIXME: This codepath is reachable under `associated_const_equality` and in the
|
||||
// future will be reachable by `min_generic_const_args`. We should handle inference
|
||||
// variables and generic parameters properly instead of doing nothing.
|
||||
(uv.args, param_env)
|
||||
};
|
||||
let uv = ty::UnevaluatedConst::new(uv.def, args);
|
||||
|
|
|
@ -1735,7 +1735,7 @@ impl<T: Clone, A: Allocator + Clone> Clone for Box<T, A> {
|
|||
// Pre-allocate memory to allow writing the cloned value directly.
|
||||
let mut boxed = Self::new_uninit_in(self.1.clone());
|
||||
unsafe {
|
||||
(**self).clone_to_uninit(boxed.as_mut_ptr());
|
||||
(**self).clone_to_uninit(boxed.as_mut_ptr().cast());
|
||||
boxed.assume_init()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -289,40 +289,12 @@ impl<K: Clone, V: Clone, A: Allocator + Clone> Clone for BTreeMap<K, V, A> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<K, Q: ?Sized, A: Allocator + Clone> super::Recover<Q> for BTreeMap<K, SetValZST, A>
|
||||
where
|
||||
K: Borrow<Q> + Ord,
|
||||
Q: Ord,
|
||||
{
|
||||
type Key = K;
|
||||
|
||||
fn get(&self, key: &Q) -> Option<&K> {
|
||||
let root_node = self.root.as_ref()?.reborrow();
|
||||
match root_node.search_tree(key) {
|
||||
Found(handle) => Some(handle.into_kv().0),
|
||||
GoDown(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn take(&mut self, key: &Q) -> Option<K> {
|
||||
let (map, dormant_map) = DormantMutRef::new(self);
|
||||
let root_node = map.root.as_mut()?.borrow_mut();
|
||||
match root_node.search_tree(key) {
|
||||
Found(handle) => Some(
|
||||
OccupiedEntry {
|
||||
handle,
|
||||
dormant_map,
|
||||
alloc: (*map.alloc).clone(),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
.remove_kv()
|
||||
.0,
|
||||
),
|
||||
GoDown(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn replace(&mut self, key: K) -> Option<K> {
|
||||
/// Internal functionality for `BTreeSet`.
|
||||
impl<K, A: Allocator + Clone> BTreeMap<K, SetValZST, A> {
|
||||
pub(super) fn replace(&mut self, key: K) -> Option<K>
|
||||
where
|
||||
K: Ord,
|
||||
{
|
||||
let (map, dormant_map) = DormantMutRef::new(self);
|
||||
let root_node =
|
||||
map.root.get_or_insert_with(|| Root::new((*map.alloc).clone())).borrow_mut();
|
||||
|
|
|
@ -12,11 +12,3 @@ mod search;
|
|||
pub mod set;
|
||||
mod set_val;
|
||||
mod split;
|
||||
|
||||
trait Recover<Q: ?Sized> {
|
||||
type Key;
|
||||
|
||||
fn get(&self, key: &Q) -> Option<&Self::Key>;
|
||||
fn take(&mut self, key: &Q) -> Option<Self::Key>;
|
||||
fn replace(&mut self, key: Self::Key) -> Option<Self::Key>;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use core::iter::{FusedIterator, Peekable};
|
|||
use core::mem::ManuallyDrop;
|
||||
use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub};
|
||||
|
||||
use super::Recover;
|
||||
use super::map::{BTreeMap, Keys};
|
||||
use super::merge_iter::MergeIterInner;
|
||||
use super::set_val::SetValZST;
|
||||
|
@ -635,7 +634,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
|
|||
T: Borrow<Q> + Ord,
|
||||
Q: Ord,
|
||||
{
|
||||
Recover::get(&self.map, value)
|
||||
self.map.get_key_value(value).map(|(k, _)| k)
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` has no elements in common with `other`.
|
||||
|
@ -926,7 +925,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
|
|||
where
|
||||
T: Ord,
|
||||
{
|
||||
Recover::replace(&mut self.map, value)
|
||||
self.map.replace(value)
|
||||
}
|
||||
|
||||
/// If the set contains an element equal to the value, removes it from the
|
||||
|
@ -978,7 +977,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
|
|||
T: Borrow<Q> + Ord,
|
||||
Q: Ord,
|
||||
{
|
||||
Recover::take(&mut self.map, value)
|
||||
self.map.remove_entry(value).map(|(k, _)| k)
|
||||
}
|
||||
|
||||
/// Retains only the elements specified by the predicate.
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
/// * `BTreeMap<T, ()>` (possible user-defined map)
|
||||
/// * `BTreeMap<T, SetValZST>` (internal set representation)
|
||||
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Default)]
|
||||
pub struct SetValZST;
|
||||
pub(super) struct SetValZST;
|
||||
|
||||
/// A trait to differentiate between `BTreeMap` and `BTreeSet` values.
|
||||
/// Returns `true` only for type `SetValZST`, `false` for all other types (blanket implementation).
|
||||
/// `TypeId` requires a `'static` lifetime, use of this trait avoids that restriction.
|
||||
///
|
||||
/// [`TypeId`]: std::any::TypeId
|
||||
pub trait IsSetVal {
|
||||
pub(super) trait IsSetVal {
|
||||
fn is_set_val() -> bool;
|
||||
}
|
||||
|
||||
|
|
|
@ -1876,7 +1876,7 @@ impl<T: ?Sized + CloneToUninit, A: Allocator + Clone> Rc<T, A> {
|
|||
// Initialize with clone of this.
|
||||
let initialized_clone = unsafe {
|
||||
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
|
||||
this_data_ref.clone_to_uninit(in_progress.data_ptr());
|
||||
this_data_ref.clone_to_uninit(in_progress.data_ptr().cast());
|
||||
// Cast type of pointer, now that it is initialized.
|
||||
in_progress.into_rc()
|
||||
};
|
||||
|
|
|
@ -2272,7 +2272,7 @@ impl<T: ?Sized + CloneToUninit, A: Allocator + Clone> Arc<T, A> {
|
|||
|
||||
let initialized_clone = unsafe {
|
||||
// Clone. If the clone panics, `in_progress` will be dropped and clean up.
|
||||
this_data_ref.clone_to_uninit(in_progress.data_ptr());
|
||||
this_data_ref.clone_to_uninit(in_progress.data_ptr().cast());
|
||||
// Cast type of pointer, now that it is initialized.
|
||||
in_progress.into_arc()
|
||||
};
|
||||
|
|
|
@ -232,20 +232,20 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
|
|||
pub unsafe trait CloneToUninit {
|
||||
/// Performs copy-assignment from `self` to `dst`.
|
||||
///
|
||||
/// This is analogous to `std::ptr::write(dst, self.clone())`,
|
||||
/// This is analogous to `std::ptr::write(dst.cast(), self.clone())`,
|
||||
/// except that `self` may be a dynamically-sized type ([`!Sized`](Sized)).
|
||||
///
|
||||
/// Before this function is called, `dst` may point to uninitialized memory.
|
||||
/// After this function is called, `dst` will point to initialized memory; it will be
|
||||
/// sound to create a `&Self` reference from the pointer.
|
||||
/// sound to create a `&Self` reference from the pointer with the [pointer metadata]
|
||||
/// from `self`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Behavior is undefined if any of the following conditions are violated:
|
||||
///
|
||||
/// * `dst` must be [valid] for writes.
|
||||
/// * `dst` must be properly aligned.
|
||||
/// * `dst` must have the same [pointer metadata] (slice length or `dyn` vtable) as `self`.
|
||||
/// * `dst` must be [valid] for writes for `std::mem::size_of_val(self)` bytes.
|
||||
/// * `dst` must be properly aligned to `std::mem::align_of_val(self)`.
|
||||
///
|
||||
/// [valid]: crate::ptr#safety
|
||||
/// [pointer metadata]: crate::ptr::metadata()
|
||||
|
@ -266,15 +266,15 @@ pub unsafe trait CloneToUninit {
|
|||
/// that might have already been created. (For example, if a `[Foo]` of length 3 is being
|
||||
/// cloned, and the second of the three calls to `Foo::clone()` unwinds, then the first `Foo`
|
||||
/// cloned should be dropped.)
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self);
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8);
|
||||
}
|
||||
|
||||
#[unstable(feature = "clone_to_uninit", issue = "126799")]
|
||||
unsafe impl<T: Clone> CloneToUninit for T {
|
||||
#[inline]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
// SAFETY: we're calling a specialization with the same contract
|
||||
unsafe { <T as self::uninit::CopySpec>::clone_one(self, dst) }
|
||||
unsafe { <T as self::uninit::CopySpec>::clone_one(self, dst.cast::<T>()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,7 +282,8 @@ unsafe impl<T: Clone> CloneToUninit for T {
|
|||
unsafe impl<T: Clone> CloneToUninit for [T] {
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
let dst: *mut [T] = dst.with_metadata_of(self);
|
||||
// SAFETY: we're calling a specialization with the same contract
|
||||
unsafe { <T as self::uninit::CopySpec>::clone_slice(self, dst) }
|
||||
}
|
||||
|
@ -292,21 +293,21 @@ unsafe impl<T: Clone> CloneToUninit for [T] {
|
|||
unsafe impl CloneToUninit for str {
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
// SAFETY: str is just a [u8] with UTF-8 invariant
|
||||
unsafe { self.as_bytes().clone_to_uninit(dst as *mut [u8]) }
|
||||
unsafe { self.as_bytes().clone_to_uninit(dst) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "clone_to_uninit", issue = "126799")]
|
||||
unsafe impl CloneToUninit for crate::ffi::CStr {
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
// SAFETY: For now, CStr is just a #[repr(trasnsparent)] [c_char] with some invariants.
|
||||
// And we can cast [c_char] to [u8] on all supported platforms (see: to_bytes_with_nul).
|
||||
// The pointer metadata properly preserves the length (NUL included).
|
||||
// The pointer metadata properly preserves the length (so NUL is also copied).
|
||||
// See: `cstr_metadata_is_length_with_nul` in tests.
|
||||
unsafe { self.to_bytes_with_nul().clone_to_uninit(dst as *mut [u8]) }
|
||||
unsafe { self.to_bytes_with_nul().clone_to_uninit(dst) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ macro_rules! impl_general_format {
|
|||
($($t:ident)*) => {
|
||||
$(impl GeneralFormat for $t {
|
||||
fn already_rounded_value_should_use_exponential(&self) -> bool {
|
||||
let abs = $t::abs_private(*self);
|
||||
let abs = $t::abs(*self);
|
||||
(abs != 0.0 && abs < 1e-4) || abs >= 1e+16
|
||||
}
|
||||
})*
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -58,7 +58,7 @@
|
|||
//!
|
||||
//! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover
|
||||
//! a small percentage of possible errors. Far more extensive tests are located in the directory
|
||||
//! `src/etc/test-float-parse` as a Python script.
|
||||
//! `src/etc/test-float-parse` as a Rust program.
|
||||
//!
|
||||
//! A note on integer overflow: Many parts of this file perform arithmetic with the decimal
|
||||
//! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit,
|
||||
|
|
|
@ -285,17 +285,6 @@ impl f128 {
|
|||
self != self
|
||||
}
|
||||
|
||||
// FIXME(#50145): `abs` is publicly unavailable in core due to
|
||||
// concerns about portability, so this implementation is for
|
||||
// private use internally.
|
||||
#[inline]
|
||||
pub(crate) const fn abs_private(self) -> f128 {
|
||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||
unsafe {
|
||||
mem::transmute::<u128, f128>(mem::transmute::<f128, u128>(self) & !Self::SIGN_MASK)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if this value is positive infinity or negative infinity, and
|
||||
/// `false` otherwise.
|
||||
///
|
||||
|
@ -345,10 +334,11 @@ impl f128 {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[rustc_allow_const_fn_unstable(const_float_methods)] // for `abs`
|
||||
pub const fn is_finite(self) -> bool {
|
||||
// There's no need to handle NaN separately: if self is NaN,
|
||||
// the comparison is not true, exactly as desired.
|
||||
self.abs_private() < Self::INFINITY
|
||||
self.abs() < Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is [subnormal].
|
||||
|
@ -836,8 +826,8 @@ impl f128 {
|
|||
const HI: f128 = f128::MAX / 2.;
|
||||
|
||||
let (a, b) = (self, other);
|
||||
let abs_a = a.abs_private();
|
||||
let abs_b = b.abs_private();
|
||||
let abs_a = a.abs();
|
||||
let abs_b = b.abs();
|
||||
|
||||
if abs_a <= HI && abs_b <= HI {
|
||||
// Overflow is impossible
|
||||
|
@ -1281,4 +1271,100 @@ impl f128 {
|
|||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
///
|
||||
/// let x = 3.5_f128;
|
||||
/// let y = -3.5_f128;
|
||||
///
|
||||
/// assert_eq!(x.abs(), x);
|
||||
/// assert_eq!(y.abs(), -y);
|
||||
///
|
||||
/// assert!(f128::NAN.abs().is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn abs(self) -> Self {
|
||||
// FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
|
||||
// We don't do this now because LLVM has lowering bugs for f128 math.
|
||||
Self::from_bits(self.to_bits() & !(1 << 127))
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// - NaN if the number is NaN
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
///
|
||||
/// let f = 3.5_f128;
|
||||
///
|
||||
/// assert_eq!(f.signum(), 1.0);
|
||||
/// assert_eq!(f128::NEG_INFINITY.signum(), -1.0);
|
||||
///
|
||||
/// assert!(f128::NAN.signum().is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn signum(self) -> f128 {
|
||||
if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) }
|
||||
}
|
||||
|
||||
/// Returns a number composed of the magnitude of `self` and the sign of
|
||||
/// `sign`.
|
||||
///
|
||||
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
|
||||
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
|
||||
/// returned.
|
||||
///
|
||||
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
|
||||
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
|
||||
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
|
||||
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
|
||||
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
|
||||
/// info.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
///
|
||||
/// let f = 3.5_f128;
|
||||
///
|
||||
/// assert_eq!(f.copysign(0.42), 3.5_f128);
|
||||
/// assert_eq!(f.copysign(-0.42), -3.5_f128);
|
||||
/// assert_eq!((-f).copysign(0.42), 3.5_f128);
|
||||
/// assert_eq!((-f).copysign(-0.42), -3.5_f128);
|
||||
///
|
||||
/// assert!(f128::NAN.copysign(1.0).is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn copysign(self, sign: f128) -> f128 {
|
||||
// SAFETY: this is actually a safe intrinsic
|
||||
unsafe { intrinsics::copysignf128(self, sign) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -279,15 +279,6 @@ impl f16 {
|
|||
self != self
|
||||
}
|
||||
|
||||
// FIXMxE(#50145): `abs` is publicly unavailable in core due to
|
||||
// concerns about portability, so this implementation is for
|
||||
// private use internally.
|
||||
#[inline]
|
||||
pub(crate) const fn abs_private(self) -> f16 {
|
||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||
unsafe { mem::transmute::<u16, f16>(mem::transmute::<f16, u16>(self) & !Self::SIGN_MASK) }
|
||||
}
|
||||
|
||||
/// Returns `true` if this value is positive infinity or negative infinity, and
|
||||
/// `false` otherwise.
|
||||
///
|
||||
|
@ -335,10 +326,11 @@ impl f16 {
|
|||
#[inline]
|
||||
#[must_use]
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
#[rustc_allow_const_fn_unstable(const_float_methods)] // for `abs`
|
||||
pub const fn is_finite(self) -> bool {
|
||||
// There's no need to handle NaN separately: if self is NaN,
|
||||
// the comparison is not true, exactly as desired.
|
||||
self.abs_private() < Self::INFINITY
|
||||
self.abs() < Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is [subnormal].
|
||||
|
@ -821,8 +813,8 @@ impl f16 {
|
|||
const HI: f16 = f16::MAX / 2.;
|
||||
|
||||
let (a, b) = (self, other);
|
||||
let abs_a = a.abs_private();
|
||||
let abs_b = b.abs_private();
|
||||
let abs_a = a.abs();
|
||||
let abs_b = b.abs();
|
||||
|
||||
if abs_a <= HI && abs_b <= HI {
|
||||
// Overflow is impossible
|
||||
|
@ -1256,4 +1248,99 @@ impl f16 {
|
|||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
///
|
||||
/// let x = 3.5_f16;
|
||||
/// let y = -3.5_f16;
|
||||
///
|
||||
/// assert_eq!(x.abs(), x);
|
||||
/// assert_eq!(y.abs(), -y);
|
||||
///
|
||||
/// assert!(f16::NAN.abs().is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn abs(self) -> Self {
|
||||
// FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
|
||||
Self::from_bits(self.to_bits() & !(1 << 15))
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// - NaN if the number is NaN
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
///
|
||||
/// let f = 3.5_f16;
|
||||
///
|
||||
/// assert_eq!(f.signum(), 1.0);
|
||||
/// assert_eq!(f16::NEG_INFINITY.signum(), -1.0);
|
||||
///
|
||||
/// assert!(f16::NAN.signum().is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn signum(self) -> f16 {
|
||||
if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
|
||||
}
|
||||
|
||||
/// Returns a number composed of the magnitude of `self` and the sign of
|
||||
/// `sign`.
|
||||
///
|
||||
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
|
||||
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
|
||||
/// returned.
|
||||
///
|
||||
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
|
||||
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
|
||||
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
|
||||
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
|
||||
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
|
||||
/// info.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
|
||||
///
|
||||
/// let f = 3.5_f16;
|
||||
///
|
||||
/// assert_eq!(f.copysign(0.42), 3.5_f16);
|
||||
/// assert_eq!(f.copysign(-0.42), -3.5_f16);
|
||||
/// assert_eq!((-f).copysign(0.42), 3.5_f16);
|
||||
/// assert_eq!((-f).copysign(-0.42), -3.5_f16);
|
||||
///
|
||||
/// assert!(f16::NAN.copysign(1.0).is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn copysign(self, sign: f16) -> f16 {
|
||||
// SAFETY: this is actually a safe intrinsic
|
||||
unsafe { intrinsics::copysignf16(self, sign) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -525,15 +525,6 @@ impl f32 {
|
|||
self != self
|
||||
}
|
||||
|
||||
// FIXME(#50145): `abs` is publicly unavailable in core due to
|
||||
// concerns about portability, so this implementation is for
|
||||
// private use internally.
|
||||
#[inline]
|
||||
pub(crate) const fn abs_private(self) -> f32 {
|
||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||
unsafe { mem::transmute::<u32, f32>(mem::transmute::<f32, u32>(self) & !Self::SIGN_MASK) }
|
||||
}
|
||||
|
||||
/// Returns `true` if this value is positive infinity or negative infinity, and
|
||||
/// `false` otherwise.
|
||||
///
|
||||
|
@ -578,10 +569,11 @@ impl f32 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
|
||||
#[inline]
|
||||
#[rustc_allow_const_fn_unstable(const_float_methods)] // for `abs`
|
||||
pub const fn is_finite(self) -> bool {
|
||||
// There's no need to handle NaN separately: if self is NaN,
|
||||
// the comparison is not true, exactly as desired.
|
||||
self.abs_private() < Self::INFINITY
|
||||
self.abs() < Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is [subnormal].
|
||||
|
@ -1019,8 +1011,8 @@ impl f32 {
|
|||
const HI: f32 = f32::MAX / 2.;
|
||||
|
||||
let (a, b) = (self, other);
|
||||
let abs_a = a.abs_private();
|
||||
let abs_b = b.abs_private();
|
||||
let abs_a = a.abs();
|
||||
let abs_b = b.abs();
|
||||
|
||||
if abs_a <= HI && abs_b <= HI {
|
||||
// Overflow is impossible
|
||||
|
@ -1424,4 +1416,87 @@ impl f32 {
|
|||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let x = 3.5_f32;
|
||||
/// let y = -3.5_f32;
|
||||
///
|
||||
/// assert_eq!(x.abs(), x);
|
||||
/// assert_eq!(y.abs(), -y);
|
||||
///
|
||||
/// assert!(f32::NAN.abs().is_nan());
|
||||
/// ```
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn abs(self) -> f32 {
|
||||
// SAFETY: this is actually a safe intrinsic
|
||||
unsafe { intrinsics::fabsf32(self) }
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// - NaN if the number is NaN
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let f = 3.5_f32;
|
||||
///
|
||||
/// assert_eq!(f.signum(), 1.0);
|
||||
/// assert_eq!(f32::NEG_INFINITY.signum(), -1.0);
|
||||
///
|
||||
/// assert!(f32::NAN.signum().is_nan());
|
||||
/// ```
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn signum(self) -> f32 {
|
||||
if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) }
|
||||
}
|
||||
|
||||
/// Returns a number composed of the magnitude of `self` and the sign of
|
||||
/// `sign`.
|
||||
///
|
||||
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
|
||||
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
|
||||
/// returned.
|
||||
///
|
||||
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
|
||||
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
|
||||
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
|
||||
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
|
||||
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
|
||||
/// info.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let f = 3.5_f32;
|
||||
///
|
||||
/// assert_eq!(f.copysign(0.42), 3.5_f32);
|
||||
/// assert_eq!(f.copysign(-0.42), -3.5_f32);
|
||||
/// assert_eq!((-f).copysign(0.42), 3.5_f32);
|
||||
/// assert_eq!((-f).copysign(-0.42), -3.5_f32);
|
||||
///
|
||||
/// assert!(f32::NAN.copysign(1.0).is_nan());
|
||||
/// ```
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[inline]
|
||||
#[stable(feature = "copysign", since = "1.35.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
pub const fn copysign(self, sign: f32) -> f32 {
|
||||
// SAFETY: this is actually a safe intrinsic
|
||||
unsafe { intrinsics::copysignf32(self, sign) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -524,15 +524,6 @@ impl f64 {
|
|||
self != self
|
||||
}
|
||||
|
||||
// FIXME(#50145): `abs` is publicly unavailable in core due to
|
||||
// concerns about portability, so this implementation is for
|
||||
// private use internally.
|
||||
#[inline]
|
||||
pub(crate) const fn abs_private(self) -> f64 {
|
||||
// SAFETY: This transmutation is fine just like in `to_bits`/`from_bits`.
|
||||
unsafe { mem::transmute::<u64, f64>(mem::transmute::<f64, u64>(self) & !Self::SIGN_MASK) }
|
||||
}
|
||||
|
||||
/// Returns `true` if this value is positive infinity or negative infinity, and
|
||||
/// `false` otherwise.
|
||||
///
|
||||
|
@ -577,10 +568,11 @@ impl f64 {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "const_float_classify", since = "1.83.0")]
|
||||
#[inline]
|
||||
#[rustc_allow_const_fn_unstable(const_float_methods)] // for `abs`
|
||||
pub const fn is_finite(self) -> bool {
|
||||
// There's no need to handle NaN separately: if self is NaN,
|
||||
// the comparison is not true, exactly as desired.
|
||||
self.abs_private() < Self::INFINITY
|
||||
self.abs() < Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is [subnormal].
|
||||
|
@ -1022,8 +1014,8 @@ impl f64 {
|
|||
const HI: f64 = f64::MAX / 2.;
|
||||
|
||||
let (a, b) = (self, other);
|
||||
let abs_a = a.abs_private();
|
||||
let abs_b = b.abs_private();
|
||||
let abs_a = a.abs();
|
||||
let abs_b = b.abs();
|
||||
|
||||
if abs_a <= HI && abs_b <= HI {
|
||||
// Overflow is impossible
|
||||
|
@ -1424,4 +1416,87 @@ impl f64 {
|
|||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let x = 3.5_f64;
|
||||
/// let y = -3.5_f64;
|
||||
///
|
||||
/// assert_eq!(x.abs(), x);
|
||||
/// assert_eq!(y.abs(), -y);
|
||||
///
|
||||
/// assert!(f64::NAN.abs().is_nan());
|
||||
/// ```
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn abs(self) -> f64 {
|
||||
// SAFETY: this is actually a safe intrinsic
|
||||
unsafe { intrinsics::fabsf64(self) }
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// - NaN if the number is NaN
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let f = 3.5_f64;
|
||||
///
|
||||
/// assert_eq!(f.signum(), 1.0);
|
||||
/// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
|
||||
///
|
||||
/// assert!(f64::NAN.signum().is_nan());
|
||||
/// ```
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn signum(self) -> f64 {
|
||||
if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) }
|
||||
}
|
||||
|
||||
/// Returns a number composed of the magnitude of `self` and the sign of
|
||||
/// `sign`.
|
||||
///
|
||||
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
|
||||
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
|
||||
/// returned.
|
||||
///
|
||||
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
|
||||
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
|
||||
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
|
||||
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
|
||||
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
|
||||
/// info.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let f = 3.5_f64;
|
||||
///
|
||||
/// assert_eq!(f.copysign(0.42), 3.5_f64);
|
||||
/// assert_eq!(f.copysign(-0.42), -3.5_f64);
|
||||
/// assert_eq!((-f).copysign(0.42), 3.5_f64);
|
||||
/// assert_eq!((-f).copysign(-0.42), -3.5_f64);
|
||||
///
|
||||
/// assert!(f64::NAN.copysign(1.0).is_nan());
|
||||
/// ```
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "copysign", since = "1.35.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn copysign(self, sign: f64) -> f64 {
|
||||
// SAFETY: this is actually a safe intrinsic
|
||||
unsafe { intrinsics::copysignf64(self, sign) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ fn test_clone_to_uninit_slice_success() {
|
|||
|
||||
let mut storage: MaybeUninit<[String; 3]> = MaybeUninit::uninit();
|
||||
let b: [String; 3] = unsafe {
|
||||
a[..].clone_to_uninit(storage.as_mut_ptr() as *mut [String]);
|
||||
a[..].clone_to_uninit(storage.as_mut_ptr().cast());
|
||||
storage.assume_init()
|
||||
};
|
||||
|
||||
|
@ -70,7 +70,7 @@ fn test_clone_to_uninit_slice_drops_on_panic() {
|
|||
let mut storage: MaybeUninit<[CountsDropsAndPanics; 3]> = MaybeUninit::uninit();
|
||||
// This should panic halfway through
|
||||
unsafe {
|
||||
a[..].clone_to_uninit(storage.as_mut_ptr() as *mut [CountsDropsAndPanics]);
|
||||
a[..].clone_to_uninit(storage.as_mut_ptr().cast());
|
||||
}
|
||||
})
|
||||
.unwrap_err();
|
||||
|
@ -89,13 +89,13 @@ fn test_clone_to_uninit_str() {
|
|||
let a = "hello";
|
||||
|
||||
let mut storage: MaybeUninit<[u8; 5]> = MaybeUninit::uninit();
|
||||
unsafe { a.clone_to_uninit(storage.as_mut_ptr() as *mut [u8] as *mut str) };
|
||||
unsafe { a.clone_to_uninit(storage.as_mut_ptr().cast()) };
|
||||
assert_eq!(a.as_bytes(), unsafe { storage.assume_init() }.as_slice());
|
||||
|
||||
let mut b: Box<str> = "world".into();
|
||||
assert_eq!(a.len(), b.len());
|
||||
assert_ne!(a, &*b);
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<str>(&mut b)) };
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<str>(&mut b).cast()) };
|
||||
assert_eq!(a, &*b);
|
||||
}
|
||||
|
||||
|
@ -104,13 +104,13 @@ fn test_clone_to_uninit_cstr() {
|
|||
let a = c"hello";
|
||||
|
||||
let mut storage: MaybeUninit<[u8; 6]> = MaybeUninit::uninit();
|
||||
unsafe { a.clone_to_uninit(storage.as_mut_ptr() as *mut [u8] as *mut CStr) };
|
||||
unsafe { a.clone_to_uninit(storage.as_mut_ptr().cast()) };
|
||||
assert_eq!(a.to_bytes_with_nul(), unsafe { storage.assume_init() }.as_slice());
|
||||
|
||||
let mut b: Box<CStr> = c"world".into();
|
||||
assert_eq!(a.count_bytes(), b.count_bytes());
|
||||
assert_ne!(a, &*b);
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<CStr>(&mut b)) };
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<CStr>(&mut b).cast()) };
|
||||
assert_eq!(a, &*b);
|
||||
}
|
||||
|
||||
|
|
|
@ -188,104 +188,6 @@ impl f128 {
|
|||
self - self.trunc()
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128)] {
|
||||
///
|
||||
/// let x = 3.5_f128;
|
||||
/// let y = -3.5_f128;
|
||||
///
|
||||
/// assert_eq!(x.abs(), x);
|
||||
/// assert_eq!(y.abs(), -y);
|
||||
///
|
||||
/// assert!(f128::NAN.abs().is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn abs(self) -> Self {
|
||||
// FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
|
||||
// We don't do this now because LLVM has lowering bugs for f128 math.
|
||||
Self::from_bits(self.to_bits() & !(1 << 127))
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// - NaN if the number is NaN
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 3.5_f128;
|
||||
///
|
||||
/// assert_eq!(f.signum(), 1.0);
|
||||
/// assert_eq!(f128::NEG_INFINITY.signum(), -1.0);
|
||||
///
|
||||
/// assert!(f128::NAN.signum().is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn signum(self) -> f128 {
|
||||
if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) }
|
||||
}
|
||||
|
||||
/// Returns a number composed of the magnitude of `self` and the sign of
|
||||
/// `sign`.
|
||||
///
|
||||
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
|
||||
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
|
||||
/// returned.
|
||||
///
|
||||
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
|
||||
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
|
||||
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
|
||||
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
|
||||
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
|
||||
/// info.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f128)]
|
||||
/// # #[cfg(reliable_f128_math)] {
|
||||
///
|
||||
/// let f = 3.5_f128;
|
||||
///
|
||||
/// assert_eq!(f.copysign(0.42), 3.5_f128);
|
||||
/// assert_eq!(f.copysign(-0.42), -3.5_f128);
|
||||
/// assert_eq!((-f).copysign(0.42), 3.5_f128);
|
||||
/// assert_eq!((-f).copysign(-0.42), -3.5_f128);
|
||||
///
|
||||
/// assert!(f128::NAN.copysign(1.0).is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[unstable(feature = "f128", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn copysign(self, sign: f128) -> f128 {
|
||||
unsafe { intrinsics::copysignf128(self, sign) }
|
||||
}
|
||||
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
||||
/// error, yielding a more accurate result than an unfused multiply-add.
|
||||
///
|
||||
|
|
|
@ -188,103 +188,6 @@ impl f16 {
|
|||
self - self.trunc()
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16)] {
|
||||
///
|
||||
/// let x = 3.5_f16;
|
||||
/// let y = -3.5_f16;
|
||||
///
|
||||
/// assert_eq!(x.abs(), x);
|
||||
/// assert_eq!(y.abs(), -y);
|
||||
///
|
||||
/// assert!(f16::NAN.abs().is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn abs(self) -> Self {
|
||||
// FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
|
||||
Self::from_bits(self.to_bits() & !(1 << 15))
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// - NaN if the number is NaN
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 3.5_f16;
|
||||
///
|
||||
/// assert_eq!(f.signum(), 1.0);
|
||||
/// assert_eq!(f16::NEG_INFINITY.signum(), -1.0);
|
||||
///
|
||||
/// assert!(f16::NAN.signum().is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn signum(self) -> f16 {
|
||||
if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
|
||||
}
|
||||
|
||||
/// Returns a number composed of the magnitude of `self` and the sign of
|
||||
/// `sign`.
|
||||
///
|
||||
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
|
||||
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
|
||||
/// returned.
|
||||
///
|
||||
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
|
||||
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
|
||||
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
|
||||
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
|
||||
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
|
||||
/// info.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(f16)]
|
||||
/// # #[cfg(reliable_f16_math)] {
|
||||
///
|
||||
/// let f = 3.5_f16;
|
||||
///
|
||||
/// assert_eq!(f.copysign(0.42), 3.5_f16);
|
||||
/// assert_eq!(f.copysign(-0.42), -3.5_f16);
|
||||
/// assert_eq!((-f).copysign(0.42), 3.5_f16);
|
||||
/// assert_eq!((-f).copysign(-0.42), -3.5_f16);
|
||||
///
|
||||
/// assert!(f16::NAN.copysign(1.0).is_nan());
|
||||
/// # }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[unstable(feature = "f16", issue = "116909")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
pub const fn copysign(self, sign: f16) -> f16 {
|
||||
unsafe { intrinsics::copysignf16(self, sign) }
|
||||
}
|
||||
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
||||
/// error, yielding a more accurate result than an unfused multiply-add.
|
||||
///
|
||||
|
|
|
@ -176,90 +176,6 @@ impl f32 {
|
|||
self - self.trunc()
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let x = 3.5_f32;
|
||||
/// let y = -3.5_f32;
|
||||
///
|
||||
/// assert_eq!(x.abs(), x);
|
||||
/// assert_eq!(y.abs(), -y);
|
||||
///
|
||||
/// assert!(f32::NAN.abs().is_nan());
|
||||
/// ```
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn abs(self) -> f32 {
|
||||
unsafe { intrinsics::fabsf32(self) }
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// - NaN if the number is NaN
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let f = 3.5_f32;
|
||||
///
|
||||
/// assert_eq!(f.signum(), 1.0);
|
||||
/// assert_eq!(f32::NEG_INFINITY.signum(), -1.0);
|
||||
///
|
||||
/// assert!(f32::NAN.signum().is_nan());
|
||||
/// ```
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn signum(self) -> f32 {
|
||||
if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) }
|
||||
}
|
||||
|
||||
/// Returns a number composed of the magnitude of `self` and the sign of
|
||||
/// `sign`.
|
||||
///
|
||||
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
|
||||
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
|
||||
/// returned.
|
||||
///
|
||||
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
|
||||
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
|
||||
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
|
||||
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
|
||||
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
|
||||
/// info.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let f = 3.5_f32;
|
||||
///
|
||||
/// assert_eq!(f.copysign(0.42), 3.5_f32);
|
||||
/// assert_eq!(f.copysign(-0.42), -3.5_f32);
|
||||
/// assert_eq!((-f).copysign(0.42), 3.5_f32);
|
||||
/// assert_eq!((-f).copysign(-0.42), -3.5_f32);
|
||||
///
|
||||
/// assert!(f32::NAN.copysign(1.0).is_nan());
|
||||
/// ```
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[inline]
|
||||
#[stable(feature = "copysign", since = "1.35.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
pub const fn copysign(self, sign: f32) -> f32 {
|
||||
unsafe { intrinsics::copysignf32(self, sign) }
|
||||
}
|
||||
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
||||
/// error, yielding a more accurate result than an unfused multiply-add.
|
||||
///
|
||||
|
|
|
@ -176,90 +176,6 @@ impl f64 {
|
|||
self - self.trunc()
|
||||
}
|
||||
|
||||
/// Computes the absolute value of `self`.
|
||||
///
|
||||
/// This function always returns the precise result.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let x = 3.5_f64;
|
||||
/// let y = -3.5_f64;
|
||||
///
|
||||
/// assert_eq!(x.abs(), x);
|
||||
/// assert_eq!(y.abs(), -y);
|
||||
///
|
||||
/// assert!(f64::NAN.abs().is_nan());
|
||||
/// ```
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn abs(self) -> f64 {
|
||||
unsafe { intrinsics::fabsf64(self) }
|
||||
}
|
||||
|
||||
/// Returns a number that represents the sign of `self`.
|
||||
///
|
||||
/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
|
||||
/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
|
||||
/// - NaN if the number is NaN
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let f = 3.5_f64;
|
||||
///
|
||||
/// assert_eq!(f.signum(), 1.0);
|
||||
/// assert_eq!(f64::NEG_INFINITY.signum(), -1.0);
|
||||
///
|
||||
/// assert!(f64::NAN.signum().is_nan());
|
||||
/// ```
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn signum(self) -> f64 {
|
||||
if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) }
|
||||
}
|
||||
|
||||
/// Returns a number composed of the magnitude of `self` and the sign of
|
||||
/// `sign`.
|
||||
///
|
||||
/// Equal to `self` if the sign of `self` and `sign` are the same, otherwise equal to `-self`.
|
||||
/// If `self` is a NaN, then a NaN with the same payload as `self` and the sign bit of `sign` is
|
||||
/// returned.
|
||||
///
|
||||
/// If `sign` is a NaN, then this operation will still carry over its sign into the result. Note
|
||||
/// that IEEE 754 doesn't assign any meaning to the sign bit in case of a NaN, and as Rust
|
||||
/// doesn't guarantee that the bit pattern of NaNs are conserved over arithmetic operations, the
|
||||
/// result of `copysign` with `sign` being a NaN might produce an unexpected or non-portable
|
||||
/// result. See the [specification of NaN bit patterns](primitive@f32#nan-bit-patterns) for more
|
||||
/// info.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let f = 3.5_f64;
|
||||
///
|
||||
/// assert_eq!(f.copysign(0.42), 3.5_f64);
|
||||
/// assert_eq!(f.copysign(-0.42), -3.5_f64);
|
||||
/// assert_eq!((-f).copysign(0.42), 3.5_f64);
|
||||
/// assert_eq!((-f).copysign(-0.42), -3.5_f64);
|
||||
///
|
||||
/// assert!(f64::NAN.copysign(1.0).is_nan());
|
||||
/// ```
|
||||
#[rustc_allow_incoherent_impl]
|
||||
#[must_use = "method returns a new number and does not mutate the original value"]
|
||||
#[stable(feature = "copysign", since = "1.35.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
|
||||
#[inline]
|
||||
pub const fn copysign(self, sign: f64) -> f64 {
|
||||
unsafe { intrinsics::copysignf64(self, sign) }
|
||||
}
|
||||
|
||||
/// Fused multiply-add. Computes `(self * a) + b` with only one rounding
|
||||
/// error, yielding a more accurate result than an unfused multiply-add.
|
||||
///
|
||||
|
|
|
@ -112,7 +112,7 @@ impl crate::sealed::Sealed for OsString {}
|
|||
/// [conversions]: super#conversions
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "OsStr")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
// `OsStr::from_inner` current implementation relies
|
||||
// `OsStr::from_inner` and `impl CloneToUninit for OsStr` current implementation relies
|
||||
// on `OsStr` being layout-compatible with `Slice`.
|
||||
// However, `OsStr` layout is considered an implementation detail and must not be relied upon.
|
||||
#[repr(transparent)]
|
||||
|
@ -1278,9 +1278,9 @@ impl Clone for Box<OsStr> {
|
|||
unsafe impl CloneToUninit for OsStr {
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
// SAFETY: we're just a wrapper around a platform-specific Slice
|
||||
unsafe { self.inner.clone_to_uninit(&raw mut (*dst).inner) }
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
// SAFETY: we're just a transparent wrapper around a platform-specific Slice
|
||||
unsafe { self.inner.clone_to_uninit(dst) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -294,12 +294,12 @@ fn clone_to_uninit() {
|
|||
let a = OsStr::new("hello.txt");
|
||||
|
||||
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<OsStr>(a)];
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut OsStr) };
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
|
||||
assert_eq!(a.as_encoded_bytes(), unsafe { MaybeUninit::slice_assume_init_ref(&storage) });
|
||||
|
||||
let mut b: Box<OsStr> = OsStr::new("world.exe").into();
|
||||
assert_eq!(size_of_val::<OsStr>(a), size_of_val::<OsStr>(&b));
|
||||
assert_ne!(a, &*b);
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<OsStr>(&mut b)) };
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<OsStr>(&mut b).cast()) };
|
||||
assert_eq!(a, &*b);
|
||||
}
|
||||
|
|
|
@ -2128,7 +2128,7 @@ impl AsRef<OsStr> for PathBuf {
|
|||
/// ```
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "Path")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
// `Path::new` current implementation relies
|
||||
// `Path::new` and `impl CloneToUninit for Path` current implementation relies
|
||||
// on `Path` being layout-compatible with `OsStr`.
|
||||
// However, `Path` layout is considered an implementation detail and must not be relied upon.
|
||||
#[repr(transparent)]
|
||||
|
@ -3170,9 +3170,9 @@ impl Path {
|
|||
unsafe impl CloneToUninit for Path {
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
// SAFETY: Path is just a wrapper around OsStr
|
||||
unsafe { self.inner.clone_to_uninit(&raw mut (*dst).inner) }
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
// SAFETY: Path is just a transparent wrapper around OsStr
|
||||
unsafe { self.inner.clone_to_uninit(dst) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2068,7 +2068,7 @@ fn clone_to_uninit() {
|
|||
let a = Path::new("hello.txt");
|
||||
|
||||
let mut storage = vec![MaybeUninit::<u8>::uninit(); size_of_val::<Path>(a)];
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()) as *mut Path) };
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<[_]>(storage.as_mut_slice()).cast()) };
|
||||
assert_eq!(a.as_os_str().as_encoded_bytes(), unsafe {
|
||||
MaybeUninit::slice_assume_init_ref(&storage)
|
||||
});
|
||||
|
@ -2076,6 +2076,6 @@ fn clone_to_uninit() {
|
|||
let mut b: Box<Path> = Path::new("world.exe").into();
|
||||
assert_eq!(size_of_val::<Path>(a), size_of_val::<Path>(&b));
|
||||
assert_ne!(a, &*b);
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b)) };
|
||||
unsafe { a.clone_to_uninit(ptr::from_mut::<Path>(&mut b).cast()) };
|
||||
assert_eq!(a, &*b);
|
||||
}
|
||||
|
|
|
@ -352,8 +352,8 @@ impl Slice {
|
|||
unsafe impl CloneToUninit for Slice {
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
// SAFETY: we're just a wrapper around [u8]
|
||||
unsafe { self.inner.clone_to_uninit(&raw mut (*dst).inner) }
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
// SAFETY: we're just a transparent wrapper around [u8]
|
||||
unsafe { self.inner.clone_to_uninit(dst) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -275,8 +275,8 @@ impl Slice {
|
|||
unsafe impl CloneToUninit for Slice {
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
// SAFETY: we're just a wrapper around Wtf8
|
||||
unsafe { self.inner.clone_to_uninit(&raw mut (*dst).inner) }
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
// SAFETY: we're just a transparent wrapper around Wtf8
|
||||
unsafe { self.inner.clone_to_uninit(dst) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1052,8 +1052,8 @@ impl Hash for Wtf8 {
|
|||
unsafe impl CloneToUninit for Wtf8 {
|
||||
#[inline]
|
||||
#[cfg_attr(debug_assertions, track_caller)]
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut Self) {
|
||||
// SAFETY: we're just a wrapper around [u8]
|
||||
unsafe { self.bytes.clone_to_uninit(&raw mut (*dst).bytes) }
|
||||
unsafe fn clone_to_uninit(&self, dst: *mut u8) {
|
||||
// SAFETY: we're just a transparent wrapper around [u8]
|
||||
unsafe { self.bytes.clone_to_uninit(dst) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
// Regression test for #132955 checking that we handle anon consts with
|
||||
// inference variables in their generic arguments correctly.
|
||||
//
|
||||
// This arose via diagnostics where we would have some failing goal such
|
||||
// as `[u8; AnonConst<Self>]: PartialEq<Self::A>`, then as part of diagnostics
|
||||
// we would replace all generic parameters with inference vars which would yield
|
||||
// a self type of `[u8; AnonConst<?x>]` and then attempt to normalize `AnonConst<?x>`.
|
||||
|
||||
pub trait T {
|
||||
type A;
|
||||
const P: Self::A;
|
||||
|
||||
fn a() {
|
||||
[0u8; std::mem::size_of::<Self::A>()] == Self::P;
|
||||
//~^ ERROR: can't compare
|
||||
//~| ERROR: constant expression depends on a generic parameter
|
||||
//~| ERROR: constant expression depends on a generic parameter
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,31 @@
|
|||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:15
|
||||
|
|
||||
LL | [0u8; std::mem::size_of::<Self::A>()] == Self::P;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error: constant expression depends on a generic parameter
|
||||
--> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:47
|
||||
|
|
||||
LL | [0u8; std::mem::size_of::<Self::A>()] == Self::P;
|
||||
| ^^
|
||||
|
|
||||
= note: this may fail depending on what value the parameter takes
|
||||
|
||||
error[E0277]: can't compare `[u8; std::mem::size_of::<Self::A>()]` with `<Self as T>::A`
|
||||
--> $DIR/failing_goal_with_repeat_expr_anon_const.rs:14:47
|
||||
|
|
||||
LL | [0u8; std::mem::size_of::<Self::A>()] == Self::P;
|
||||
| ^^ no implementation for `[u8; std::mem::size_of::<Self::A>()] == <Self as T>::A`
|
||||
|
|
||||
= help: the trait `PartialEq<<Self as T>::A>` is not implemented for `[u8; std::mem::size_of::<Self::A>()]`
|
||||
help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
LL | pub trait T where [u8; std::mem::size_of::<Self::A>()]: PartialEq<<Self as T>::A> {
|
||||
| +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
46
tests/ui/inline-const/cross_const_control_flow.rs
Normal file
46
tests/ui/inline-const/cross_const_control_flow.rs
Normal file
|
@ -0,0 +1,46 @@
|
|||
//@edition:2021
|
||||
|
||||
fn foo() {
|
||||
const { return }
|
||||
//~^ ERROR: return statement outside of function body
|
||||
}
|
||||
|
||||
fn labelled_block_break() {
|
||||
'a: { const { break 'a } }
|
||||
//~^ ERROR: `break` outside of a loop or labeled block
|
||||
//~| ERROR: use of unreachable label
|
||||
}
|
||||
|
||||
fn loop_break() {
|
||||
loop {
|
||||
const { break }
|
||||
//~^ ERROR: `break` outside of a loop or labeled block
|
||||
}
|
||||
}
|
||||
|
||||
fn continue_to_labelled_block() {
|
||||
'a: { const { continue 'a } }
|
||||
//~^ ERROR: `continue` outside of a loop
|
||||
//~| ERROR: use of unreachable label
|
||||
}
|
||||
|
||||
fn loop_continue() {
|
||||
loop {
|
||||
const { continue }
|
||||
//~^ ERROR: `continue` outside of a loop
|
||||
}
|
||||
}
|
||||
|
||||
async fn await_across_const_block() {
|
||||
const { async {}.await }
|
||||
//~^ ERROR: `await` is only allowed inside `async` functions and blocks
|
||||
}
|
||||
|
||||
fn reference_to_non_constant_in_const_block() {
|
||||
let x = 1;
|
||||
const { &x };
|
||||
//~^ ERROR: attempt to use a non-constant value in a constant
|
||||
}
|
||||
|
||||
|
||||
fn main() {}
|
78
tests/ui/inline-const/cross_const_control_flow.stderr
Normal file
78
tests/ui/inline-const/cross_const_control_flow.stderr
Normal file
|
@ -0,0 +1,78 @@
|
|||
error[E0767]: use of unreachable label `'a`
|
||||
--> $DIR/cross_const_control_flow.rs:9:25
|
||||
|
|
||||
LL | 'a: { const { break 'a } }
|
||||
| -- ^^ unreachable label `'a`
|
||||
| |
|
||||
| unreachable label defined here
|
||||
|
|
||||
= note: labels are unreachable through functions, closures, async blocks and modules
|
||||
|
||||
error[E0767]: use of unreachable label `'a`
|
||||
--> $DIR/cross_const_control_flow.rs:22:28
|
||||
|
|
||||
LL | 'a: { const { continue 'a } }
|
||||
| -- ^^ unreachable label `'a`
|
||||
| |
|
||||
| unreachable label defined here
|
||||
|
|
||||
= note: labels are unreachable through functions, closures, async blocks and modules
|
||||
|
||||
error[E0435]: attempt to use a non-constant value in a constant
|
||||
--> $DIR/cross_const_control_flow.rs:41:14
|
||||
|
|
||||
LL | const { &x };
|
||||
| ^ non-constant value
|
||||
|
|
||||
help: consider using `const` instead of `let`
|
||||
|
|
||||
LL | const x: /* Type */ = 1;
|
||||
| ~~~~~ ++++++++++++
|
||||
|
||||
error[E0728]: `await` is only allowed inside `async` functions and blocks
|
||||
--> $DIR/cross_const_control_flow.rs:35:22
|
||||
|
|
||||
LL | const { async {}.await }
|
||||
| -----------^^^^^--
|
||||
| | |
|
||||
| | only allowed inside `async` functions and blocks
|
||||
| this is not `async`
|
||||
|
||||
error[E0268]: `break` outside of a loop or labeled block
|
||||
--> $DIR/cross_const_control_flow.rs:9:19
|
||||
|
|
||||
LL | 'a: { const { break 'a } }
|
||||
| ^^^^^^^^ cannot `break` outside of a loop or labeled block
|
||||
|
||||
error[E0268]: `break` outside of a loop or labeled block
|
||||
--> $DIR/cross_const_control_flow.rs:16:17
|
||||
|
|
||||
LL | const { break }
|
||||
| ^^^^^ cannot `break` outside of a loop or labeled block
|
||||
|
||||
error[E0268]: `continue` outside of a loop
|
||||
--> $DIR/cross_const_control_flow.rs:22:19
|
||||
|
|
||||
LL | 'a: { const { continue 'a } }
|
||||
| ^^^^^^^^^^^ cannot `continue` outside of a loop
|
||||
|
||||
error[E0268]: `continue` outside of a loop
|
||||
--> $DIR/cross_const_control_flow.rs:29:17
|
||||
|
|
||||
LL | const { continue }
|
||||
| ^^^^^^^^ cannot `continue` outside of a loop
|
||||
|
||||
error[E0572]: return statement outside of function body
|
||||
--> $DIR/cross_const_control_flow.rs:4:13
|
||||
|
|
||||
LL | / fn foo() {
|
||||
LL | | const { return }
|
||||
| | --^^^^^^-- the return is part of this body...
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_- ...not the enclosing function body
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0268, E0435, E0572, E0728, E0767.
|
||||
For more information about an error, try `rustc --explain E0268`.
|
Loading…
Add table
Reference in a new issue