Auto merge of #131747 - compiler-errors:rollup-0fnymws, r=compiler-errors

Rollup of 7 pull requests

Successful merges:

 - #129794 (uefi: Implement getcwd and chdir)
 - #130568 (Make some float methods unstable `const fn`)
 - #131521 (rename RcBox to RcInner for consistency)
 - #131701 (Don't report `on_unimplemented` message for negative traits)
 - #131705 (Fix most ui tests on emscripten target)
 - #131733 (Fix uninlined_format_args in stable_mir)
 - #131734 (Update `arm64e-apple-tvos` maintainer)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2024-10-15 19:55:10 +00:00
commit e7c0d27507
45 changed files with 767 additions and 419 deletions

View File

@ -992,10 +992,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
match op.val {
Pair(data_ptr, meta) => {
// In the case of Rc<Self>, we need to explicitly pass a
// *mut RcBox<Self> with a Scalar (not ScalarPair) ABI. This is a hack
// *mut RcInner<Self> with a Scalar (not ScalarPair) ABI. This is a hack
// that is understood elsewhere in the compiler as a method on
// `dyn Trait`.
// To get a `*mut RcBox<Self>`, we just keep unwrapping newtypes until
// To get a `*mut RcInner<Self>`, we just keep unwrapping newtypes until
// we get a value of a built-in pointer type.
//
// This is also relevant for `Pin<&mut Self>`, where we need to peel the

View File

@ -334,19 +334,6 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
{
use rustc_type_ir::TyKind::*;
fn adjust_nan<
'tcx,
M: Machine<'tcx>,
F1: rustc_apfloat::Float + FloatConvert<F2>,
F2: rustc_apfloat::Float,
>(
ecx: &InterpCx<'tcx, M>,
f1: F1,
f2: F2,
) -> F2 {
if f2.is_nan() { M::generate_nan(ecx, &[f1]) } else { f2 }
}
match *dest_ty.kind() {
// float -> uint
Uint(t) => {
@ -367,11 +354,17 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
}
// float -> float
Float(fty) => match fty {
FloatTy::F16 => Scalar::from_f16(adjust_nan(self, f, f.convert(&mut false).value)),
FloatTy::F32 => Scalar::from_f32(adjust_nan(self, f, f.convert(&mut false).value)),
FloatTy::F64 => Scalar::from_f64(adjust_nan(self, f, f.convert(&mut false).value)),
FloatTy::F16 => {
Scalar::from_f16(self.adjust_nan(f.convert(&mut false).value, &[f]))
}
FloatTy::F32 => {
Scalar::from_f32(self.adjust_nan(f.convert(&mut false).value, &[f]))
}
FloatTy::F64 => {
Scalar::from_f64(self.adjust_nan(f.convert(&mut false).value, &[f]))
}
FloatTy::F128 => {
Scalar::from_f128(adjust_nan(self, f, f.convert(&mut false).value))
Scalar::from_f128(self.adjust_nan(f.convert(&mut false).value, &[f]))
}
},
// That's it.

View File

@ -599,6 +599,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
pub fn generate_stacktrace(&self) -> Vec<FrameInfo<'tcx>> {
Frame::generate_stacktrace_from_stack(self.stack())
}
pub fn adjust_nan<F1, F2>(&self, f: F2, inputs: &[F1]) -> F2
where
F1: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F2>,
F2: rustc_apfloat::Float,
{
if f.is_nan() { M::generate_nan(self, inputs) } else { f }
}
}
#[doc(hidden)]

View File

@ -4,6 +4,7 @@
use std::assert_matches::assert_matches;
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
use rustc_hir::def_id::DefId;
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement};
@ -438,6 +439,26 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.write_scalar(Scalar::from_target_usize(align.bytes(), self), dest)?;
}
sym::minnumf16 => self.float_min_intrinsic::<Half>(args, dest)?,
sym::minnumf32 => self.float_min_intrinsic::<Single>(args, dest)?,
sym::minnumf64 => self.float_min_intrinsic::<Double>(args, dest)?,
sym::minnumf128 => self.float_min_intrinsic::<Quad>(args, dest)?,
sym::maxnumf16 => self.float_max_intrinsic::<Half>(args, dest)?,
sym::maxnumf32 => self.float_max_intrinsic::<Single>(args, dest)?,
sym::maxnumf64 => self.float_max_intrinsic::<Double>(args, dest)?,
sym::maxnumf128 => self.float_max_intrinsic::<Quad>(args, dest)?,
sym::copysignf16 => self.float_copysign_intrinsic::<Half>(args, dest)?,
sym::copysignf32 => self.float_copysign_intrinsic::<Single>(args, dest)?,
sym::copysignf64 => self.float_copysign_intrinsic::<Double>(args, dest)?,
sym::copysignf128 => self.float_copysign_intrinsic::<Quad>(args, dest)?,
sym::fabsf16 => self.float_abs_intrinsic::<Half>(args, dest)?,
sym::fabsf32 => self.float_abs_intrinsic::<Single>(args, dest)?,
sym::fabsf64 => self.float_abs_intrinsic::<Double>(args, dest)?,
sym::fabsf128 => self.float_abs_intrinsic::<Quad>(args, dest)?,
// Unsupported intrinsic: skip the return_to_block below.
_ => return interp_ok(false),
}
@ -697,4 +718,63 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
let rhs_bytes = get_bytes(self, rhs)?;
interp_ok(Scalar::from_bool(lhs_bytes == rhs_bytes))
}
fn float_min_intrinsic<F>(
&mut self,
args: &[OpTy<'tcx, M::Provenance>],
dest: &MPlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, ()>
where
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
{
let a: F = self.read_scalar(&args[0])?.to_float()?;
let b: F = self.read_scalar(&args[1])?.to_float()?;
let res = self.adjust_nan(a.min(b), &[a, b]);
self.write_scalar(res, dest)?;
interp_ok(())
}
fn float_max_intrinsic<F>(
&mut self,
args: &[OpTy<'tcx, M::Provenance>],
dest: &MPlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, ()>
where
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
{
let a: F = self.read_scalar(&args[0])?.to_float()?;
let b: F = self.read_scalar(&args[1])?.to_float()?;
let res = self.adjust_nan(a.max(b), &[a, b]);
self.write_scalar(res, dest)?;
interp_ok(())
}
fn float_copysign_intrinsic<F>(
&mut self,
args: &[OpTy<'tcx, M::Provenance>],
dest: &MPlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, ()>
where
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
{
let a: F = self.read_scalar(&args[0])?.to_float()?;
let b: F = self.read_scalar(&args[1])?.to_float()?;
// bitwise, no NaN adjustments
self.write_scalar(a.copy_sign(b), dest)?;
interp_ok(())
}
fn float_abs_intrinsic<F>(
&mut self,
args: &[OpTy<'tcx, M::Provenance>],
dest: &MPlaceTy<'tcx, M::Provenance>,
) -> InterpResult<'tcx, ()>
where
F: rustc_apfloat::Float + rustc_apfloat::FloatConvert<F> + Into<Scalar<M::Provenance>>,
{
let x: F = self.read_scalar(&args[0])?.to_float()?;
// bitwise, no NaN adjustments
self.write_scalar(x.abs(), dest)?;
interp_ok(())
}
}

View File

@ -64,8 +64,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
use rustc_middle::mir::BinOp::*;
// Performs appropriate non-deterministic adjustments of NaN results.
let adjust_nan =
|f: F| -> F { if f.is_nan() { M::generate_nan(self, &[l, r]) } else { f } };
let adjust_nan = |f: F| -> F { self.adjust_nan(f, &[l, r]) };
match bin_op {
Eq => ImmTy::from_bool(l == r, *self.tcx),

View File

@ -960,7 +960,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
continue;
}
unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
predicate.kind().rebind(p.trait_ref),
predicate.kind().rebind(p),
Obligation {
cause: cause.clone(),
param_env: self.param_env,

View File

@ -202,7 +202,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
notes,
parent_label,
append_const_msg,
} = self.on_unimplemented_note(main_trait_ref, o, &mut long_ty_file);
} = self.on_unimplemented_note(main_trait_predicate, o, &mut long_ty_file);
let have_alt_message = message.is_some() || label.is_some();
let is_try_conversion = self.is_try_conversion(span, main_trait_ref.def_id());

View File

@ -9,7 +9,7 @@ use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_macros::LintDiagnostic;
use rustc_middle::bug;
use rustc_middle::ty::print::PrintTraitRefExt as _;
use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, TyCtxt};
use rustc_middle::ty::{self, GenericArgsRef, GenericParamDefKind, ToPolyTraitRef, TyCtxt};
use rustc_parse_format::{ParseMode, Parser, Piece, Position};
use rustc_session::lint::builtin::UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES;
use rustc_span::Span;
@ -108,14 +108,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
pub fn on_unimplemented_note(
&self,
trait_ref: ty::PolyTraitRef<'tcx>,
trait_pred: ty::PolyTraitPredicate<'tcx>,
obligation: &PredicateObligation<'tcx>,
long_ty_file: &mut Option<PathBuf>,
) -> OnUnimplementedNote {
if trait_pred.polarity() != ty::PredicatePolarity::Positive {
return OnUnimplementedNote::default();
}
let (def_id, args) = self
.impl_similar_to(trait_ref, obligation)
.unwrap_or_else(|| (trait_ref.def_id(), trait_ref.skip_binder().args));
let trait_ref = trait_ref.skip_binder();
.impl_similar_to(trait_pred.to_poly_trait_ref(), obligation)
.unwrap_or_else(|| (trait_pred.def_id(), trait_pred.skip_binder().trait_ref.args));
let trait_pred = trait_pred.skip_binder();
let mut flags = vec![];
// FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): HIR is not present for RPITITs,
@ -144,13 +148,13 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
flags.push((sym::cause, Some("MainFunctionType".to_string())));
}
flags.push((sym::Trait, Some(trait_ref.print_trait_sugared().to_string())));
flags.push((sym::Trait, Some(trait_pred.trait_ref.print_trait_sugared().to_string())));
// Add all types without trimmed paths or visible paths, ensuring they end up with
// their "canonical" def path.
ty::print::with_no_trimmed_paths!(ty::print::with_no_visible_paths!({
let generics = self.tcx.generics_of(def_id);
let self_ty = trait_ref.self_ty();
let self_ty = trait_pred.self_ty();
// This is also included through the generics list as `Self`,
// but the parser won't allow you to use it
flags.push((sym::_Self, Some(self_ty.to_string())));
@ -266,7 +270,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
}));
if let Ok(Some(command)) = OnUnimplementedDirective::of_item(self.tcx, def_id) {
command.evaluate(self.tcx, trait_ref, &flags, long_ty_file)
command.evaluate(self.tcx, trait_pred.trait_ref, &flags, long_ty_file)
} else {
OnUnimplementedNote::default()
}

View File

@ -822,10 +822,10 @@ fn make_thin_self_ptr<'tcx>(
_ => bug!("receiver type has unsupported layout: {:?}", layout),
}
// In the case of Rc<Self>, we need to explicitly pass a *mut RcBox<Self>
// In the case of Rc<Self>, we need to explicitly pass a *mut RcInner<Self>
// with a Scalar (not ScalarPair) ABI. This is a hack that is understood
// elsewhere in the compiler as a method on a `dyn Trait`.
// To get the type `*mut RcBox<Self>`, we just keep unwrapping newtypes until we
// To get the type `*mut RcInner<Self>`, we just keep unwrapping newtypes until we
// get a built-in pointer type
let mut wide_pointer_layout = layout;
while !wide_pointer_layout.ty.is_unsafe_ptr() && !wide_pointer_layout.ty.is_ref() {
@ -838,7 +838,7 @@ fn make_thin_self_ptr<'tcx>(
wide_pointer_layout.ty
};
// we now have a type like `*mut RcBox<dyn Trait>`
// we now have a type like `*mut RcInner<dyn Trait>`
// change its layout to that of `*mut ()`, a thin pointer, but keep the same type
// this is understood as a special case elsewhere in the compiler
let unit_ptr_ty = Ty::new_mut_ptr(tcx, tcx.types.unit);

View File

@ -22,7 +22,7 @@ impl Debug for Place {
}
pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -> io::Result<()> {
write!(writer, "fn {}(", name)?;
write!(writer, "fn {name}(")?;
body.arg_locals()
.iter()
.enumerate()
@ -54,7 +54,7 @@ pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -
.iter()
.enumerate()
.map(|(index, block)| -> io::Result<()> {
writeln!(writer, " bb{}: {{", index)?;
writeln!(writer, " bb{index}: {{")?;
let _ = block
.statements
.iter()
@ -75,7 +75,7 @@ pub(crate) fn function_body<W: Write>(writer: &mut W, body: &Body, name: &str) -
fn pretty_statement<W: Write>(writer: &mut W, statement: &StatementKind) -> io::Result<()> {
match statement {
StatementKind::Assign(place, rval) => {
write!(writer, " {:?} = ", place)?;
write!(writer, " {place:?} = ")?;
pretty_rvalue(writer, rval)?;
writeln!(writer, ";")
}
@ -165,7 +165,7 @@ fn pretty_terminator_head<W: Write>(writer: &mut W, terminator: &TerminatorKind)
Abort => write!(writer, "{INDENT}abort"),
Return => write!(writer, "{INDENT}return"),
Unreachable => write!(writer, "{INDENT}unreachable"),
Drop { place, .. } => write!(writer, "{INDENT}drop({:?})", place),
Drop { place, .. } => write!(writer, "{INDENT}drop({place:?})"),
Call { func, args, destination, .. } => {
write!(writer, "{INDENT}{:?} = {}(", destination, pretty_operand(func))?;
let mut args_iter = args.iter();
@ -304,10 +304,10 @@ fn pretty_assert_message<W: Write>(writer: &mut W, msg: &AssertMessage) -> io::R
fn pretty_operand(operand: &Operand) -> String {
match operand {
Operand::Copy(copy) => {
format!("{:?}", copy)
format!("{copy:?}")
}
Operand::Move(mv) => {
format!("move {:?}", mv)
format!("move {mv:?}")
}
Operand::Constant(cnst) => pretty_mir_const(&cnst.const_),
}
@ -344,13 +344,13 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
write!(writer, "Checked{:?}({}, {})", bin, pretty_operand(op1), pretty_operand(op2))
}
Rvalue::CopyForDeref(deref) => {
write!(writer, "CopyForDeref({:?})", deref)
write!(writer, "CopyForDeref({deref:?})")
}
Rvalue::Discriminant(place) => {
write!(writer, "discriminant({:?})", place)
write!(writer, "discriminant({place:?})")
}
Rvalue::Len(len) => {
write!(writer, "len({:?})", len)
write!(writer, "len({len:?})")
}
Rvalue::Ref(_, borrowkind, place) => {
let kind = match borrowkind {
@ -359,17 +359,17 @@ fn pretty_rvalue<W: Write>(writer: &mut W, rval: &Rvalue) -> io::Result<()> {
BorrowKind::Fake(FakeBorrowKind::Shallow) => "&fake shallow ",
BorrowKind::Mut { .. } => "&mut ",
};
write!(writer, "{kind}{:?}", place)
write!(writer, "{kind}{place:?}")
}
Rvalue::Repeat(op, cnst) => {
write!(writer, "{} \" \" {}", pretty_operand(op), pretty_ty_const(cnst))
}
Rvalue::ShallowInitBox(_, _) => Ok(()),
Rvalue::ThreadLocalRef(item) => {
write!(writer, "thread_local_ref{:?}", item)
write!(writer, "thread_local_ref{item:?}")
}
Rvalue::NullaryOp(nul, ty) => {
write!(writer, "{:?} {} \" \"", nul, ty)
write!(writer, "{nul:?} {ty} \" \"")
}
Rvalue::UnaryOp(un, op) => {
write!(writer, "{} \" \" {:?}", pretty_operand(op), un)

View File

@ -282,19 +282,19 @@ mod tests;
// would interfere with otherwise safe [into|from]_raw() of transmutable
// inner types.
#[repr(C)]
struct RcBox<T: ?Sized> {
struct RcInner<T: ?Sized> {
strong: Cell<usize>,
weak: Cell<usize>,
value: T,
}
/// Calculate layout for `RcBox<T>` using the inner value's layout
fn rcbox_layout_for_value_layout(layout: Layout) -> Layout {
/// Calculate layout for `RcInner<T>` using the inner value's layout
fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout {
// Calculate layout using the given value layout.
// Previously, layout was calculated on the expression
// `&*(ptr as *const RcBox<T>)`, but this created a misaligned
// `&*(ptr as *const RcInner<T>)`, but this created a misaligned
// reference (see #54908).
Layout::new::<RcBox<()>>().extend(layout).unwrap().0.pad_to_align()
Layout::new::<RcInner<()>>().extend(layout).unwrap().0.pad_to_align()
}
/// A single-threaded reference-counting pointer. 'Rc' stands for 'Reference
@ -314,8 +314,8 @@ pub struct Rc<
T: ?Sized,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
ptr: NonNull<RcBox<T>>,
phantom: PhantomData<RcBox<T>>,
ptr: NonNull<RcInner<T>>,
phantom: PhantomData<RcInner<T>>,
alloc: A,
}
@ -343,37 +343,37 @@ impl<T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Rc<U>> for Rc<T> {}
impl<T: ?Sized> Rc<T> {
#[inline]
unsafe fn from_inner(ptr: NonNull<RcBox<T>>) -> Self {
unsafe fn from_inner(ptr: NonNull<RcInner<T>>) -> Self {
unsafe { Self::from_inner_in(ptr, Global) }
}
#[inline]
unsafe fn from_ptr(ptr: *mut RcBox<T>) -> Self {
unsafe fn from_ptr(ptr: *mut RcInner<T>) -> Self {
unsafe { Self::from_inner(NonNull::new_unchecked(ptr)) }
}
}
impl<T: ?Sized, A: Allocator> Rc<T, A> {
#[inline(always)]
fn inner(&self) -> &RcBox<T> {
fn inner(&self) -> &RcInner<T> {
// This unsafety is ok because while this Rc is alive we're guaranteed
// that the inner pointer is valid.
unsafe { self.ptr.as_ref() }
}
#[inline]
fn into_inner_with_allocator(this: Self) -> (NonNull<RcBox<T>>, A) {
fn into_inner_with_allocator(this: Self) -> (NonNull<RcInner<T>>, A) {
let this = mem::ManuallyDrop::new(this);
(this.ptr, unsafe { ptr::read(&this.alloc) })
}
#[inline]
unsafe fn from_inner_in(ptr: NonNull<RcBox<T>>, alloc: A) -> Self {
unsafe fn from_inner_in(ptr: NonNull<RcInner<T>>, alloc: A) -> Self {
Self { ptr, phantom: PhantomData, alloc }
}
#[inline]
unsafe fn from_ptr_in(ptr: *mut RcBox<T>, alloc: A) -> Self {
unsafe fn from_ptr_in(ptr: *mut RcInner<T>, alloc: A) -> Self {
unsafe { Self::from_inner_in(NonNull::new_unchecked(ptr), alloc) }
}
}
@ -397,7 +397,7 @@ impl<T> Rc<T> {
// if the weak pointer is stored inside the strong one.
unsafe {
Self::from_inner(
Box::leak(Box::new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value }))
Box::leak(Box::new(RcInner { strong: Cell::new(1), weak: Cell::new(1), value }))
.into(),
)
}
@ -546,8 +546,12 @@ impl<T> Rc<T> {
// if the weak pointer is stored inside the strong one.
unsafe {
Ok(Self::from_inner(
Box::leak(Box::try_new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value })?)
.into(),
Box::leak(Box::try_new(RcInner {
strong: Cell::new(1),
weak: Cell::new(1),
value,
})?)
.into(),
))
}
}
@ -646,7 +650,7 @@ impl<T, A: Allocator> Rc<T, A> {
// That would make code size bigger.
match Self::try_new_in(value, alloc) {
Ok(m) => m,
Err(_) => handle_alloc_error(Layout::new::<RcBox<T>>()),
Err(_) => handle_alloc_error(Layout::new::<RcInner<T>>()),
}
}
@ -765,7 +769,7 @@ impl<T, A: Allocator> Rc<T, A> {
// Construct the inner in the "uninitialized" state with a single
// weak reference.
let (uninit_raw_ptr, alloc) = Box::into_raw_with_allocator(Box::new_in(
RcBox {
RcInner {
strong: Cell::new(0),
weak: Cell::new(1),
value: mem::MaybeUninit::<T>::uninit(),
@ -773,7 +777,7 @@ impl<T, A: Allocator> Rc<T, A> {
alloc,
));
let uninit_ptr: NonNull<_> = (unsafe { &mut *uninit_raw_ptr }).into();
let init_ptr: NonNull<RcBox<T>> = uninit_ptr.cast();
let init_ptr: NonNull<RcInner<T>> = uninit_ptr.cast();
let weak = Weak { ptr: init_ptr, alloc: alloc };
@ -826,7 +830,7 @@ impl<T, A: Allocator> Rc<T, A> {
// the allocation while the strong destructor is running, even
// if the weak pointer is stored inside the strong one.
let (ptr, alloc) = Box::into_unique(Box::try_new_in(
RcBox { strong: Cell::new(1), weak: Cell::new(1), value },
RcInner { strong: Cell::new(1), weak: Cell::new(1), value },
alloc,
)?);
Ok(unsafe { Self::from_inner_in(ptr.into(), alloc) })
@ -1059,7 +1063,7 @@ impl<T> Rc<[T]> {
|layout| Global.allocate_zeroed(layout),
|mem| {
ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len)
as *mut RcBox<[mem::MaybeUninit<T>]>
as *mut RcInner<[mem::MaybeUninit<T>]>
},
))
}
@ -1132,7 +1136,7 @@ impl<T, A: Allocator> Rc<[T], A> {
|layout| alloc.allocate_zeroed(layout),
|mem| {
ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len)
as *mut RcBox<[mem::MaybeUninit<T>]>
as *mut RcInner<[mem::MaybeUninit<T>]>
},
),
alloc,
@ -1437,7 +1441,7 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
#[stable(feature = "weak_into_raw", since = "1.45.0")]
#[rustc_never_returns_null_ptr]
pub fn as_ptr(this: &Self) -> *const T {
let ptr: *mut RcBox<T> = NonNull::as_ptr(this.ptr);
let ptr: *mut RcInner<T> = NonNull::as_ptr(this.ptr);
// SAFETY: This cannot go through Deref::deref or Rc::inner because
// this is required to retain raw/mut provenance such that e.g. `get_mut` can
@ -1516,8 +1520,8 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self {
let offset = unsafe { data_offset(ptr) };
// Reverse the offset to find the original RcBox.
let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut RcBox<T> };
// Reverse the offset to find the original RcInner.
let rc_ptr = unsafe { ptr.byte_sub(offset) as *mut RcInner<T> };
unsafe { Self::from_ptr_in(rc_ptr, alloc) }
}
@ -2002,43 +2006,43 @@ impl<A: Allocator> Rc<dyn Any, A> {
}
impl<T: ?Sized> Rc<T> {
/// Allocates an `RcBox<T>` with sufficient space for
/// Allocates an `RcInner<T>` with sufficient space for
/// a possibly-unsized inner value where the value has the layout provided.
///
/// The function `mem_to_rcbox` is called with the data pointer
/// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
/// The function `mem_to_rc_inner` is called with the data pointer
/// and must return back a (potentially fat)-pointer for the `RcInner<T>`.
#[cfg(not(no_global_oom_handling))]
unsafe fn allocate_for_layout(
value_layout: Layout,
allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>,
) -> *mut RcBox<T> {
let layout = rcbox_layout_for_value_layout(value_layout);
mem_to_rc_inner: impl FnOnce(*mut u8) -> *mut RcInner<T>,
) -> *mut RcInner<T> {
let layout = rc_inner_layout_for_value_layout(value_layout);
unsafe {
Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rcbox)
Rc::try_allocate_for_layout(value_layout, allocate, mem_to_rc_inner)
.unwrap_or_else(|_| handle_alloc_error(layout))
}
}
/// Allocates an `RcBox<T>` with sufficient space for
/// Allocates an `RcInner<T>` with sufficient space for
/// a possibly-unsized inner value where the value has the layout provided,
/// returning an error if allocation fails.
///
/// The function `mem_to_rcbox` is called with the data pointer
/// and must return back a (potentially fat)-pointer for the `RcBox<T>`.
/// The function `mem_to_rc_inner` is called with the data pointer
/// and must return back a (potentially fat)-pointer for the `RcInner<T>`.
#[inline]
unsafe fn try_allocate_for_layout(
value_layout: Layout,
allocate: impl FnOnce(Layout) -> Result<NonNull<[u8]>, AllocError>,
mem_to_rcbox: impl FnOnce(*mut u8) -> *mut RcBox<T>,
) -> Result<*mut RcBox<T>, AllocError> {
let layout = rcbox_layout_for_value_layout(value_layout);
mem_to_rc_inner: impl FnOnce(*mut u8) -> *mut RcInner<T>,
) -> Result<*mut RcInner<T>, AllocError> {
let layout = rc_inner_layout_for_value_layout(value_layout);
// Allocate for the layout.
let ptr = allocate(layout)?;
// Initialize the RcBox
let inner = mem_to_rcbox(ptr.as_non_null_ptr().as_ptr());
// Initialize the RcInner
let inner = mem_to_rc_inner(ptr.as_non_null_ptr().as_ptr());
unsafe {
debug_assert_eq!(Layout::for_value_raw(inner), layout);
@ -2051,15 +2055,15 @@ impl<T: ?Sized> Rc<T> {
}
impl<T: ?Sized, A: Allocator> Rc<T, A> {
/// Allocates an `RcBox<T>` with sufficient space for an unsized inner value
/// Allocates an `RcInner<T>` with sufficient space for an unsized inner value
#[cfg(not(no_global_oom_handling))]
unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut RcBox<T> {
// Allocate for the `RcBox<T>` using the given value.
unsafe fn allocate_for_ptr_in(ptr: *const T, alloc: &A) -> *mut RcInner<T> {
// Allocate for the `RcInner<T>` using the given value.
unsafe {
Rc::<T>::allocate_for_layout(
Layout::for_value_raw(ptr),
|layout| alloc.allocate(layout),
|mem| mem.with_metadata_of(ptr as *const RcBox<T>),
|mem| mem.with_metadata_of(ptr as *const RcInner<T>),
)
}
}
@ -2088,14 +2092,14 @@ impl<T: ?Sized, A: Allocator> Rc<T, A> {
}
impl<T> Rc<[T]> {
/// Allocates an `RcBox<[T]>` with the given length.
/// Allocates an `RcInner<[T]>` with the given length.
#[cfg(not(no_global_oom_handling))]
unsafe fn allocate_for_slice(len: usize) -> *mut RcBox<[T]> {
unsafe fn allocate_for_slice(len: usize) -> *mut RcInner<[T]> {
unsafe {
Self::allocate_for_layout(
Layout::array::<T>(len).unwrap(),
|layout| Global.allocate(layout),
|mem| ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len) as *mut RcBox<[T]>,
|mem| ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len) as *mut RcInner<[T]>,
)
}
}
@ -2119,7 +2123,7 @@ impl<T> Rc<[T]> {
unsafe fn from_iter_exact(iter: impl Iterator<Item = T>, len: usize) -> Rc<[T]> {
// Panic guard while cloning T elements.
// In the event of a panic, elements that have been written
// into the new RcBox will be dropped, then the memory freed.
// into the new RcInner will be dropped, then the memory freed.
struct Guard<T> {
mem: NonNull<u8>,
elems: *mut T,
@ -2154,7 +2158,7 @@ impl<T> Rc<[T]> {
guard.n_elems += 1;
}
// All clear. Forget the guard so it doesn't free the new RcBox.
// All clear. Forget the guard so it doesn't free the new RcInner.
mem::forget(guard);
Self::from_ptr(ptr)
@ -2163,15 +2167,15 @@ impl<T> Rc<[T]> {
}
impl<T, A: Allocator> Rc<[T], A> {
/// Allocates an `RcBox<[T]>` with the given length.
/// Allocates an `RcInner<[T]>` with the given length.
#[inline]
#[cfg(not(no_global_oom_handling))]
unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut RcBox<[T]> {
unsafe fn allocate_for_slice_in(len: usize, alloc: &A) -> *mut RcInner<[T]> {
unsafe {
Rc::<[T]>::allocate_for_layout(
Layout::array::<T>(len).unwrap(),
|layout| alloc.allocate(layout),
|mem| ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len) as *mut RcBox<[T]>,
|mem| ptr::slice_from_raw_parts_mut(mem.cast::<T>(), len) as *mut RcInner<[T]>,
)
}
}
@ -2901,9 +2905,9 @@ pub struct Weak<
// but it is not necessarily a valid pointer.
// `Weak::new` sets this to `usize::MAX` so that it doesnt need
// to allocate space on the heap. That's not a value a real pointer
// will ever have because RcBox has alignment at least 2.
// will ever have because RcInner has alignment at least 2.
// This is only possible when `T: Sized`; unsized `T` never dangle.
ptr: NonNull<RcBox<T>>,
ptr: NonNull<RcInner<T>>,
alloc: A,
}
@ -2939,7 +2943,7 @@ impl<T> Weak<T> {
pub const fn new() -> Weak<T> {
Weak {
ptr: unsafe {
NonNull::new_unchecked(ptr::without_provenance_mut::<RcBox<T>>(usize::MAX))
NonNull::new_unchecked(ptr::without_provenance_mut::<RcInner<T>>(usize::MAX))
},
alloc: Global,
}
@ -2966,7 +2970,7 @@ impl<T, A: Allocator> Weak<T, A> {
pub fn new_in(alloc: A) -> Weak<T, A> {
Weak {
ptr: unsafe {
NonNull::new_unchecked(ptr::without_provenance_mut::<RcBox<T>>(usize::MAX))
NonNull::new_unchecked(ptr::without_provenance_mut::<RcInner<T>>(usize::MAX))
},
alloc,
}
@ -3070,11 +3074,11 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
#[must_use]
#[stable(feature = "rc_as_ptr", since = "1.45.0")]
pub fn as_ptr(&self) -> *const T {
let ptr: *mut RcBox<T> = NonNull::as_ptr(self.ptr);
let ptr: *mut RcInner<T> = NonNull::as_ptr(self.ptr);
if is_dangling(ptr) {
// If the pointer is dangling, we return the sentinel directly. This cannot be
// a valid payload address, as the payload is at least as aligned as RcBox (usize).
// a valid payload address, as the payload is at least as aligned as RcInner (usize).
ptr as *const T
} else {
// SAFETY: if is_dangling returns false, then the pointer is dereferenceable.
@ -3206,14 +3210,14 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
let ptr = if is_dangling(ptr) {
// This is a dangling Weak.
ptr as *mut RcBox<T>
ptr as *mut RcInner<T>
} else {
// Otherwise, we're guaranteed the pointer came from a nondangling Weak.
// SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
let offset = unsafe { data_offset(ptr) };
// Thus, we reverse the offset to get the whole RcBox.
// Thus, we reverse the offset to get the whole RcInner.
// SAFETY: the pointer originated from a Weak, so this offset is safe.
unsafe { ptr.byte_sub(offset) as *mut RcBox<T> }
unsafe { ptr.byte_sub(offset) as *mut RcInner<T> }
};
// SAFETY: we now have recovered the original Weak pointer, so can create the Weak.
@ -3288,7 +3292,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
}
}
/// Returns `None` when the pointer is dangling and there is no allocated `RcBox`,
/// Returns `None` when the pointer is dangling and there is no allocated `RcInner`,
/// (i.e., when this `Weak` was created by `Weak::new`).
#[inline]
fn inner(&self) -> Option<WeakInner<'_>> {
@ -3522,7 +3526,7 @@ trait RcInnerPtr {
}
}
impl<T: ?Sized> RcInnerPtr for RcBox<T> {
impl<T: ?Sized> RcInnerPtr for RcInner<T> {
#[inline(always)]
fn weak_ref(&self) -> &Cell<usize> {
&self.weak
@ -3563,15 +3567,15 @@ impl<T: ?Sized, A: Allocator> AsRef<T> for Rc<T, A> {
#[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized, A: Allocator> Unpin for Rc<T, A> {}
/// Gets the offset within an `RcBox` for the payload behind a pointer.
/// Gets the offset within an `RcInner` for the payload behind a pointer.
///
/// # Safety
///
/// The pointer must point to (and have valid metadata for) a previously
/// valid instance of T, but the T is allowed to be dropped.
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
// Align the unsized value to the end of the RcBox.
// Because RcBox is repr(C), it will always be the last field in memory.
// Align the unsized value to the end of the RcInner.
// Because RcInner is repr(C), it will always be the last field in memory.
// SAFETY: since the only unsized types possible are slices, trait objects,
// and extern types, the input safety requirement is currently enough to
// satisfy the requirements of align_of_val_raw; this is an implementation
@ -3581,7 +3585,7 @@ unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
#[inline]
fn data_offset_align(align: usize) -> usize {
let layout = Layout::new::<RcBox<()>>();
let layout = Layout::new::<RcInner<()>>();
layout.size() + layout.padding_needed_for(align)
}
@ -3627,8 +3631,8 @@ pub struct UniqueRc<
T: ?Sized,
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
> {
ptr: NonNull<RcBox<T>>,
phantom: PhantomData<RcBox<T>>,
ptr: NonNull<RcInner<T>>,
phantom: PhantomData<RcInner<T>>,
alloc: A,
}
@ -3664,7 +3668,7 @@ impl<T, A: Allocator> UniqueRc<T, A> {
#[unstable(feature = "unique_rc_arc", issue = "112566")]
pub fn new_in(value: T, alloc: A) -> Self {
let (ptr, alloc) = Box::into_unique(Box::new_in(
RcBox {
RcInner {
strong: Cell::new(0),
// keep one weak reference so if all the weak pointers that are created are dropped
// the UniqueRc still stays valid.
@ -3759,7 +3763,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> {
}
}
/// A unique owning pointer to a [`RcBox`] **that does not imply the contents are initialized,**
/// A unique owning pointer to a [`RcInner`] **that does not imply the contents are initialized,**
/// but will deallocate it (without dropping the value) when dropped.
///
/// This is a helper for [`Rc::make_mut()`] to ensure correct cleanup on panic.
@ -3767,21 +3771,21 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueRc<T, A> {
/// which `MaybeUninit` does not.
#[cfg(not(no_global_oom_handling))]
struct UniqueRcUninit<T: ?Sized, A: Allocator> {
ptr: NonNull<RcBox<T>>,
ptr: NonNull<RcInner<T>>,
layout_for_value: Layout,
alloc: Option<A>,
}
#[cfg(not(no_global_oom_handling))]
impl<T: ?Sized, A: Allocator> UniqueRcUninit<T, A> {
/// Allocates a RcBox with layout suitable to contain `for_value` or a clone of it.
/// Allocates a RcInner with layout suitable to contain `for_value` or a clone of it.
fn new(for_value: &T, alloc: A) -> UniqueRcUninit<T, A> {
let layout = Layout::for_value(for_value);
let ptr = unsafe {
Rc::allocate_for_layout(
layout,
|layout_for_rcbox| alloc.allocate(layout_for_rcbox),
|mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcBox<T>),
|layout_for_rc_inner| alloc.allocate(layout_for_rc_inner),
|mem| mem.with_metadata_of(ptr::from_ref(for_value) as *const RcInner<T>),
)
};
Self { ptr: NonNull::new(ptr).unwrap(), layout_for_value: layout, alloc: Some(alloc) }
@ -3816,10 +3820,10 @@ impl<T: ?Sized, A: Allocator> Drop for UniqueRcUninit<T, A> {
// * new() produced a pointer safe to deallocate.
// * We own the pointer unless into_rc() was called, which forgets us.
unsafe {
self.alloc
.take()
.unwrap()
.deallocate(self.ptr.cast(), rcbox_layout_for_value_layout(self.layout_for_value));
self.alloc.take().unwrap().deallocate(
self.ptr.cast(),
rc_inner_layout_for_value_layout(self.layout_for_value),
);
}
}
}

View File

@ -319,7 +319,7 @@ pub struct Weak<
// but it is not necessarily a valid pointer.
// `Weak::new` sets this to `usize::MAX` so that it doesnt need
// to allocate space on the heap. That's not a value a real pointer
// will ever have because RcBox has alignment at least 2.
// will ever have because RcInner has alignment at least 2.
// This is only possible when `T: Sized`; unsized `T` never dangle.
ptr: NonNull<ArcInner<T>>,
alloc: A,
@ -1581,7 +1581,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
pub fn as_ptr(this: &Self) -> *const T {
let ptr: *mut ArcInner<T> = NonNull::as_ptr(this.ptr);
// SAFETY: This cannot go through Deref::deref or RcBoxPtr::inner because
// SAFETY: This cannot go through Deref::deref or RcInnerPtr::inner because
// this is required to retain raw/mut provenance such that e.g. `get_mut` can
// write through the pointer after the Rc is recovered through `from_raw`.
unsafe { &raw mut (*ptr).data }
@ -2936,7 +2936,7 @@ impl<T: ?Sized, A: Allocator> Weak<T, A> {
// Otherwise, we're guaranteed the pointer came from a nondangling Weak.
// SAFETY: data_offset is safe to call, as ptr references a real (potentially dropped) T.
let offset = unsafe { data_offset(ptr) };
// Thus, we reverse the offset to get the whole RcBox.
// Thus, we reverse the offset to get the whole RcInner.
// SAFETY: the pointer originated from a Weak, so this offset is safe.
unsafe { ptr.byte_sub(offset) as *mut ArcInner<T> }
};
@ -3861,7 +3861,7 @@ impl<T: ?Sized, A: Allocator> Unpin for Arc<T, A> {}
/// valid instance of T, but the T is allowed to be dropped.
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> usize {
// Align the unsized value to the end of the ArcInner.
// Because RcBox is repr(C), it will always be the last field in memory.
// Because RcInner is repr(C), it will always be the last field in memory.
// SAFETY: since the only unsized types possible are slices, trait objects,
// and extern types, the input safety requirement is currently enough to
// satisfy the requirements of align_of_val_raw; this is an implementation

View File

@ -193,11 +193,11 @@
//! use std::marker::PhantomData;
//!
//! struct Rc<T: ?Sized> {
//! ptr: NonNull<RcBox<T>>,
//! phantom: PhantomData<RcBox<T>>,
//! ptr: NonNull<RcInner<T>>,
//! phantom: PhantomData<RcInner<T>>,
//! }
//!
//! struct RcBox<T: ?Sized> {
//! struct RcInner<T: ?Sized> {
//! strong: Cell<usize>,
//! refcount: Cell<usize>,
//! value: T,
@ -213,9 +213,9 @@
//! }
//! }
//!
//! trait RcBoxPtr<T: ?Sized> {
//! trait RcInnerPtr<T: ?Sized> {
//!
//! fn inner(&self) -> &RcBox<T>;
//! fn inner(&self) -> &RcInner<T>;
//!
//! fn strong(&self) -> usize {
//! self.inner().strong.get()
@ -230,8 +230,8 @@
//! }
//! }
//!
//! impl<T: ?Sized> RcBoxPtr<T> for Rc<T> {
//! fn inner(&self) -> &RcBox<T> {
//! impl<T: ?Sized> RcInnerPtr<T> for Rc<T> {
//! fn inner(&self) -> &RcInner<T> {
//! unsafe {
//! self.ptr.as_ref()
//! }

View File

@ -1849,154 +1849,6 @@ extern "rust-intrinsic" {
#[cfg(not(bootstrap))]
pub fn fmuladdf128(a: f128, b: f128, c: f128) -> f128;
/// Returns the absolute value of an `f16`.
///
/// The stabilized version of this intrinsic is
/// [`f16::abs`](../../std/primitive.f16.html#method.abs)
#[rustc_nounwind]
pub fn fabsf16(x: f16) -> f16;
/// Returns the absolute value of an `f32`.
///
/// The stabilized version of this intrinsic is
/// [`f32::abs`](../../std/primitive.f32.html#method.abs)
#[rustc_nounwind]
pub fn fabsf32(x: f32) -> f32;
/// Returns the absolute value of an `f64`.
///
/// The stabilized version of this intrinsic is
/// [`f64::abs`](../../std/primitive.f64.html#method.abs)
#[rustc_nounwind]
pub fn fabsf64(x: f64) -> f64;
/// Returns the absolute value of an `f128`.
///
/// The stabilized version of this intrinsic is
/// [`f128::abs`](../../std/primitive.f128.html#method.abs)
#[rustc_nounwind]
pub fn fabsf128(x: f128) -> f128;
/// Returns the minimum of two `f16` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f16::min`]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn minnumf16(x: f16, y: f16) -> f16;
/// Returns the minimum of two `f32` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f32::min`]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn minnumf32(x: f32, y: f32) -> f32;
/// Returns the minimum of two `f64` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f64::min`]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn minnumf64(x: f64, y: f64) -> f64;
/// Returns the minimum of two `f128` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f128::min`]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn minnumf128(x: f128, y: f128) -> f128;
/// Returns the maximum of two `f16` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f16::max`]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn maxnumf16(x: f16, y: f16) -> f16;
/// Returns the maximum of two `f32` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f32::max`]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn maxnumf32(x: f32, y: f32) -> f32;
/// Returns the maximum of two `f64` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f64::max`]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn maxnumf64(x: f64, y: f64) -> f64;
/// Returns the maximum of two `f128` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f128::max`]
#[rustc_safe_intrinsic]
#[rustc_nounwind]
pub fn maxnumf128(x: f128, y: f128) -> f128;
/// Copies the sign from `y` to `x` for `f16` values.
///
/// The stabilized version of this intrinsic is
/// [`f16::copysign`](../../std/primitive.f16.html#method.copysign)
#[rustc_nounwind]
pub fn copysignf16(x: f16, y: f16) -> f16;
/// Copies the sign from `y` to `x` for `f32` values.
///
/// The stabilized version of this intrinsic is
/// [`f32::copysign`](../../std/primitive.f32.html#method.copysign)
#[rustc_nounwind]
pub fn copysignf32(x: f32, y: f32) -> f32;
/// Copies the sign from `y` to `x` for `f64` values.
///
/// The stabilized version of this intrinsic is
/// [`f64::copysign`](../../std/primitive.f64.html#method.copysign)
#[rustc_nounwind]
pub fn copysignf64(x: f64, y: f64) -> f64;
/// Copies the sign from `y` to `x` for `f128` values.
///
/// The stabilized version of this intrinsic is
/// [`f128::copysign`](../../std/primitive.f128.html#method.copysign)
#[rustc_nounwind]
pub fn copysignf128(x: f128, y: f128) -> f128;
/// Returns the largest integer less than or equal to an `f16`.
///
/// The stabilized version of this intrinsic is
@ -3555,6 +3407,245 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
}
}
/// Returns the minimum of two `f16` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f16::min`]
#[rustc_nounwind]
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const fn minnumf16(_x: f16, _y: f16) -> f16 {
unimplemented!();
}
/// Returns the minimum of two `f32` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f32::min`]
#[rustc_nounwind]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const fn minnumf32(_x: f32, _y: f32) -> f32 {
unimplemented!();
}
/// Returns the minimum of two `f64` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f64::min`]
#[rustc_nounwind]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const fn minnumf64(_x: f64, _y: f64) -> f64 {
unimplemented!();
}
/// Returns the minimum of two `f128` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f128::min`]
#[rustc_nounwind]
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const fn minnumf128(_x: f128, _y: f128) -> f128 {
unimplemented!();
}
/// Returns the maximum of two `f16` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f16::max`]
#[rustc_nounwind]
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const fn maxnumf16(_x: f16, _y: f16) -> f16 {
unimplemented!();
}
/// Returns the maximum of two `f32` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f32::max`]
#[rustc_nounwind]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const fn maxnumf32(_x: f32, _y: f32) -> f32 {
unimplemented!();
}
/// Returns the maximum of two `f64` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f64::max`]
#[rustc_nounwind]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const fn maxnumf64(_x: f64, _y: f64) -> f64 {
unimplemented!();
}
/// Returns the maximum of two `f128` values.
///
/// Note that, unlike most intrinsics, this is safe to call;
/// it does not require an `unsafe` block.
/// Therefore, implementations must not require the user to uphold
/// any safety invariants.
///
/// The stabilized version of this intrinsic is
/// [`f128::max`]
#[rustc_nounwind]
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const fn maxnumf128(_x: f128, _y: f128) -> f128 {
unimplemented!();
}
/// Returns the absolute value of an `f16`.
///
/// The stabilized version of this intrinsic is
/// [`f16::abs`](../../std/primitive.f16.html#method.abs)
#[rustc_nounwind]
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn fabsf16(_x: f16) -> f16 {
unimplemented!();
}
/// Returns the absolute value of an `f32`.
///
/// The stabilized version of this intrinsic is
/// [`f32::abs`](../../std/primitive.f32.html#method.abs)
#[rustc_nounwind]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn fabsf32(_x: f32) -> f32 {
unimplemented!();
}
/// Returns the absolute value of an `f64`.
///
/// The stabilized version of this intrinsic is
/// [`f64::abs`](../../std/primitive.f64.html#method.abs)
#[rustc_nounwind]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn fabsf64(_x: f64) -> f64 {
unimplemented!();
}
/// Returns the absolute value of an `f128`.
///
/// The stabilized version of this intrinsic is
/// [`f128::abs`](../../std/primitive.f128.html#method.abs)
#[rustc_nounwind]
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn fabsf128(_x: f128) -> f128 {
unimplemented!();
}
/// Copies the sign from `y` to `x` for `f16` values.
///
/// The stabilized version of this intrinsic is
/// [`f16::copysign`](../../std/primitive.f16.html#method.copysign)
#[rustc_nounwind]
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_const_unstable(feature = "f16", issue = "116909")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn copysignf16(_x: f16, _y: f16) -> f16 {
unimplemented!();
}
/// Copies the sign from `y` to `x` for `f32` values.
///
/// The stabilized version of this intrinsic is
/// [`f32::copysign`](../../std/primitive.f32.html#method.copysign)
#[rustc_nounwind]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn copysignf32(_x: f32, _y: f32) -> f32 {
unimplemented!();
}
/// Copies the sign from `y` to `x` for `f64` values.
///
/// The stabilized version of this intrinsic is
/// [`f64::copysign`](../../std/primitive.f64.html#method.copysign)
#[rustc_nounwind]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn copysignf64(_x: f64, _y: f64) -> f64 {
unimplemented!();
}
/// Copies the sign from `y` to `x` for `f128` values.
///
/// The stabilized version of this intrinsic is
/// [`f128::copysign`](../../std/primitive.f128.html#method.copysign)
#[rustc_nounwind]
// #[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[rustc_const_unstable(feature = "f128", issue = "116909")]
#[rustc_intrinsic]
#[rustc_intrinsic_must_be_overridden]
pub const unsafe fn copysignf128(_x: f128, _y: f128) -> f128 {
unimplemented!();
}
/// Inform Miri that a given pointer definitely has a certain alignment.
#[cfg(miri)]
pub(crate) const fn miri_promise_symbolic_alignment(ptr: *const (), align: usize) {

View File

@ -120,6 +120,7 @@
#![feature(const_char_encode_utf16)]
#![feature(const_eval_select)]
#![feature(const_exact_div)]
#![feature(const_float_methods)]
#![feature(const_fmt_arguments_new)]
#![feature(const_hash)]
#![feature(const_heap)]

View File

@ -471,7 +471,7 @@ impl f128 {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
pub fn is_sign_positive(self) -> bool {
pub const fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}
@ -497,7 +497,7 @@ impl f128 {
#[inline]
#[must_use]
#[unstable(feature = "f128", issue = "116909")]
pub fn is_sign_negative(self) -> bool {
pub const fn is_sign_negative(self) -> bool {
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
// applies to zeros and NaNs as well.
// SAFETY: This is just transmuting to get the sign bit, it's fine.
@ -538,7 +538,7 @@ impl f128 {
#[inline]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_up(self) -> Self {
pub const fn next_up(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
// we do our best to still produce the correct result on such targets.
@ -592,7 +592,7 @@ impl f128 {
#[inline]
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_down(self) -> Self {
pub const fn next_down(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
// we do our best to still produce the correct result on such targets.
@ -627,8 +627,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn recip(self) -> Self {
pub const fn recip(self) -> Self {
1.0 / self
}
@ -647,8 +648,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_degrees(self) -> Self {
pub const fn to_degrees(self) -> Self {
// Use a literal for better precision.
const PIS_IN_180: f128 = 57.2957795130823208767981548141051703324054724665643215491602_f128;
self * PIS_IN_180
@ -670,8 +672,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_radians(self) -> f128 {
pub const fn to_radians(self) -> f128 {
// Use a literal for better precision.
const RADS_PER_DEG: f128 =
0.0174532925199432957692369076848861271344287188854172545609719_f128;
@ -698,8 +701,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn max(self, other: f128) -> f128 {
pub const fn max(self, other: f128) -> f128 {
intrinsics::maxnumf128(self, other)
}
@ -723,8 +727,9 @@ impl f128 {
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn min(self, other: f128) -> f128 {
pub const fn min(self, other: f128) -> f128 {
intrinsics::minnumf128(self, other)
}
@ -757,7 +762,7 @@ impl f128 {
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn maximum(self, other: f128) -> f128 {
pub const fn maximum(self, other: f128) -> f128 {
if self > other {
self
} else if other > self {
@ -798,7 +803,7 @@ impl f128 {
#[unstable(feature = "f128", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn minimum(self, other: f128) -> f128 {
pub const fn minimum(self, other: f128) -> f128 {
if self < other {
self
} else if other < self {
@ -1269,9 +1274,20 @@ impl f128 {
/// ```
#[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 fn clamp(mut self, min: f128, max: f128) -> f128 {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
pub const fn clamp(mut self, min: f128, max: f128) -> f128 {
#[inline] // inline to avoid LLVM crash
const fn assert_at_const(min: f128, max: f128) {
// Note that we cannot format in constant expressions.
assert!(min <= max, "min > max, or either was NaN");
}
#[inline] // inline to avoid codegen regression
fn assert_at_rt(min: f128, max: f128) {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
}
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
if self < min {
self = min;
}

View File

@ -459,7 +459,7 @@ impl f16 {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
pub fn is_sign_positive(self) -> bool {
pub const fn is_sign_positive(self) -> bool {
!self.is_sign_negative()
}
@ -488,7 +488,7 @@ impl f16 {
#[inline]
#[must_use]
#[unstable(feature = "f16", issue = "116909")]
pub fn is_sign_negative(self) -> bool {
pub const fn is_sign_negative(self) -> bool {
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
// applies to zeros and NaNs as well.
// SAFETY: This is just transmuting to get the sign bit, it's fine.
@ -529,7 +529,7 @@ impl f16 {
#[inline]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_up(self) -> Self {
pub const fn next_up(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
// we do our best to still produce the correct result on such targets.
@ -583,7 +583,7 @@ impl f16 {
#[inline]
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_next_up_down", issue = "91399")]
pub fn next_down(self) -> Self {
pub const fn next_down(self) -> Self {
// Some targets violate Rust's assumption of IEEE semantics, e.g. by flushing
// denormals to zero. This is in general unsound and unsupported, but here
// we do our best to still produce the correct result on such targets.
@ -618,8 +618,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn recip(self) -> Self {
pub const fn recip(self) -> Self {
1.0 / self
}
@ -638,8 +639,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_degrees(self) -> Self {
pub const fn to_degrees(self) -> Self {
// Use a literal for better precision.
const PIS_IN_180: f16 = 57.2957795130823208767981548141051703_f16;
self * PIS_IN_180
@ -661,8 +663,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the operation, without modifying the original"]
pub fn to_radians(self) -> f16 {
pub const fn to_radians(self) -> f16 {
// Use a literal for better precision.
const RADS_PER_DEG: f16 = 0.017453292519943295769236907684886_f16;
self * RADS_PER_DEG
@ -687,8 +690,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn max(self, other: f16) -> f16 {
pub const fn max(self, other: f16) -> f16 {
intrinsics::maxnumf16(self, other)
}
@ -711,8 +715,9 @@ impl f16 {
/// ```
#[inline]
#[unstable(feature = "f16", issue = "116909")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn min(self, other: f16) -> f16 {
pub const fn min(self, other: f16) -> f16 {
intrinsics::minnumf16(self, other)
}
@ -744,7 +749,7 @@ impl f16 {
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn maximum(self, other: f16) -> f16 {
pub const fn maximum(self, other: f16) -> f16 {
if self > other {
self
} else if other > self {
@ -784,7 +789,7 @@ impl f16 {
#[unstable(feature = "f16", issue = "116909")]
// #[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[must_use = "this returns the result of the comparison, without modifying either input"]
pub fn minimum(self, other: f16) -> f16 {
pub const fn minimum(self, other: f16) -> f16 {
if self < other {
self
} else if other < self {
@ -1244,9 +1249,20 @@ impl f16 {
/// ```
#[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 fn clamp(mut self, min: f16, max: f16) -> f16 {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
pub const fn clamp(mut self, min: f16, max: f16) -> f16 {
#[inline] // inline to avoid LLVM crash
const fn assert_at_const(min: f16, max: f16) {
// Note that we cannot format in constant expressions.
assert!(min <= max, "min > max, or either was NaN");
}
#[inline] // inline to avoid codegen regression
fn assert_at_rt(min: f16, max: f16) {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
}
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
if self < min {
self = min;
}

View File

@ -828,8 +828,9 @@ impl f32 {
/// ```
#[must_use = "this returns the result of the operation, without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn recip(self) -> f32 {
pub const fn recip(self) -> f32 {
1.0 / self
}
@ -845,8 +846,9 @@ impl f32 {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn to_degrees(self) -> f32 {
pub const fn to_degrees(self) -> f32 {
// Use a constant for better precision.
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
self * PIS_IN_180
@ -864,8 +866,9 @@ impl f32 {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn to_radians(self) -> f32 {
pub const fn to_radians(self) -> f32 {
const RADS_PER_DEG: f32 = consts::PI / 180.0;
self * RADS_PER_DEG
}
@ -885,8 +888,9 @@ impl f32 {
/// ```
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn max(self, other: f32) -> f32 {
pub const fn max(self, other: f32) -> f32 {
intrinsics::maxnumf32(self, other)
}
@ -905,8 +909,9 @@ impl f32 {
/// ```
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn min(self, other: f32) -> f32 {
pub const fn min(self, other: f32) -> f32 {
intrinsics::minnumf32(self, other)
}
@ -933,7 +938,7 @@ impl f32 {
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn maximum(self, other: f32) -> f32 {
pub const fn maximum(self, other: f32) -> f32 {
if self > other {
self
} else if other > self {
@ -968,7 +973,7 @@ impl f32 {
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn minimum(self, other: f32) -> f32 {
pub const fn minimum(self, other: f32) -> f32 {
if self < other {
self
} else if other < self {
@ -1401,9 +1406,19 @@ impl f32 {
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "clamp", since = "1.50.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn clamp(mut self, min: f32, max: f32) -> f32 {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
pub const fn clamp(mut self, min: f32, max: f32) -> f32 {
const fn assert_at_const(min: f32, max: f32) {
// Note that we cannot format in constant expressions.
assert!(min <= max, "min > max, or either was NaN");
}
#[inline] // inline to avoid codegen regression
fn assert_at_rt(min: f32, max: f32) {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
}
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
if self < min {
self = min;
}

View File

@ -845,8 +845,9 @@ impl f64 {
/// ```
#[must_use = "this returns the result of the operation, without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn recip(self) -> f64 {
pub const fn recip(self) -> f64 {
1.0 / self
}
@ -862,8 +863,9 @@ impl f64 {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn to_degrees(self) -> f64 {
pub const fn to_degrees(self) -> f64 {
// The division here is correctly rounded with respect to the true
// value of 180/π. (This differs from f32, where a constant must be
// used to ensure a correctly rounded result.)
@ -882,8 +884,9 @@ impl f64 {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn to_radians(self) -> f64 {
pub const fn to_radians(self) -> f64 {
const RADS_PER_DEG: f64 = consts::PI / 180.0;
self * RADS_PER_DEG
}
@ -903,8 +906,9 @@ impl f64 {
/// ```
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn max(self, other: f64) -> f64 {
pub const fn max(self, other: f64) -> f64 {
intrinsics::maxnumf64(self, other)
}
@ -923,8 +927,9 @@ impl f64 {
/// ```
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn min(self, other: f64) -> f64 {
pub const fn min(self, other: f64) -> f64 {
intrinsics::minnumf64(self, other)
}
@ -951,7 +956,7 @@ impl f64 {
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn maximum(self, other: f64) -> f64 {
pub const fn maximum(self, other: f64) -> f64 {
if self > other {
self
} else if other > self {
@ -986,7 +991,7 @@ impl f64 {
#[must_use = "this returns the result of the comparison, without modifying either input"]
#[unstable(feature = "float_minimum_maximum", issue = "91079")]
#[inline]
pub fn minimum(self, other: f64) -> f64 {
pub const fn minimum(self, other: f64) -> f64 {
if self < other {
self
} else if other < self {
@ -1401,9 +1406,19 @@ impl f64 {
/// ```
#[must_use = "method returns a new number and does not mutate the original value"]
#[stable(feature = "clamp", since = "1.50.0")]
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
#[inline]
pub fn clamp(mut self, min: f64, max: f64) -> f64 {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
pub const fn clamp(mut self, min: f64, max: f64) -> f64 {
const fn assert_at_const(min: f64, max: f64) {
// Note that we cannot format in constant expressions.
assert!(min <= max, "min > max, or either was NaN");
}
#[inline] // inline to avoid codegen regression
fn assert_at_rt(min: f64, max: f64) {
assert!(min <= max, "min > max, or either was NaN. min = {min:?}, max = {max:?}");
}
// FIXME(const-hack): We would prefer to have streamlined panics when formatters become const-friendly.
intrinsics::const_eval_select((min, max), assert_at_const, assert_at_rt);
if self < min {
self = min;
}

View File

@ -210,8 +210,9 @@ impl f128 {
#[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 fn abs(self) -> Self {
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))
@ -240,8 +241,9 @@ impl f128 {
#[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 fn signum(self) -> f128 {
pub const fn signum(self) -> f128 {
if self.is_nan() { Self::NAN } else { 1.0_f128.copysign(self) }
}
@ -278,8 +280,9 @@ impl f128 {
#[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 fn copysign(self, sign: f128) -> f128 {
pub const fn copysign(self, sign: f128) -> f128 {
unsafe { intrinsics::copysignf128(self, sign) }
}

View File

@ -210,8 +210,9 @@ impl f16 {
#[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 fn abs(self) -> Self {
pub const fn abs(self) -> Self {
// FIXME(f16_f128): replace with `intrinsics::fabsf16` when available
Self::from_bits(self.to_bits() & !(1 << 15))
}
@ -239,8 +240,9 @@ impl f16 {
#[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 fn signum(self) -> f16 {
pub const fn signum(self) -> f16 {
if self.is_nan() { Self::NAN } else { 1.0_f16.copysign(self) }
}
@ -277,8 +279,9 @@ impl f16 {
#[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 fn copysign(self, sign: f16) -> f16 {
pub const fn copysign(self, sign: f16) -> f16 {
unsafe { intrinsics::copysignf16(self, sign) }
}

View File

@ -194,8 +194,9 @@ impl f32 {
#[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 fn abs(self) -> f32 {
pub const fn abs(self) -> f32 {
unsafe { intrinsics::fabsf32(self) }
}
@ -218,8 +219,9 @@ impl f32 {
#[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 fn signum(self) -> f32 {
pub const fn signum(self) -> f32 {
if self.is_nan() { Self::NAN } else { 1.0_f32.copysign(self) }
}
@ -253,7 +255,8 @@ impl f32 {
#[must_use = "method returns a new number and does not mutate the original value"]
#[inline]
#[stable(feature = "copysign", since = "1.35.0")]
pub fn copysign(self, sign: f32) -> f32 {
#[rustc_const_unstable(feature = "const_float_methods", issue = "130843")]
pub const fn copysign(self, sign: f32) -> f32 {
unsafe { intrinsics::copysignf32(self, sign) }
}

View File

@ -194,8 +194,9 @@ impl f64 {
#[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 fn abs(self) -> f64 {
pub const fn abs(self) -> f64 {
unsafe { intrinsics::fabsf64(self) }
}
@ -218,8 +219,9 @@ impl f64 {
#[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 fn signum(self) -> f64 {
pub const fn signum(self) -> f64 {
if self.is_nan() { Self::NAN } else { 1.0_f64.copysign(self) }
}
@ -252,8 +254,9 @@ impl f64 {
#[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 fn copysign(self, sign: f64) -> f64 {
pub const fn copysign(self, sign: f64) -> f64 {
unsafe { intrinsics::copysignf64(self, sign) }
}

View File

@ -289,6 +289,7 @@
#![feature(cfg_target_thread_local)]
#![feature(cfi_encoding)]
#![feature(concat_idents)]
#![feature(const_float_methods)]
#![feature(decl_macro)]
#![feature(deprecated_suggestion)]
#![feature(doc_cfg)]

View File

@ -177,16 +177,8 @@ pub(crate) fn device_path_to_text(path: NonNull<device_path::Protocol>) -> io::R
)
};
// SAFETY: `convert_device_path_to_text` returns a pointer to a null-terminated UTF-16
// string, and that string cannot be deallocated prior to dropping the `WStrUnits`, so
// it's safe for `WStrUnits` to use.
let path_len = unsafe {
WStrUnits::new(path_ptr)
.ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?
.count()
};
let path = OsString::from_wide(unsafe { slice::from_raw_parts(path_ptr.cast(), path_len) });
let path = os_string_from_raw(path_ptr)
.ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?;
if let Some(boot_services) = crate::os::uefi::env::boot_services() {
let boot_services: NonNull<r_efi::efi::BootServices> = boot_services.cast();
@ -420,3 +412,15 @@ impl<T> Drop for OwnedTable<T> {
unsafe { crate::alloc::dealloc(self.ptr as *mut u8, self.layout) };
}
}
/// Create OsString from a pointer to NULL terminated UTF-16 string
pub(crate) fn os_string_from_raw(ptr: *mut r_efi::efi::Char16) -> Option<OsString> {
let path_len = unsafe { WStrUnits::new(ptr)?.count() };
Some(OsString::from_wide(unsafe { slice::from_raw_parts(ptr.cast(), path_len) }))
}
/// Create NULL terminated UTF-16 string
pub(crate) fn os_string_to_raw(s: &OsStr) -> Option<Box<[r_efi::efi::Char16]>> {
let temp = s.encode_wide().chain(Some(0)).collect::<Box<[r_efi::efi::Char16]>>();
if temp[..temp.len() - 1].contains(&0) { None } else { Some(temp) }
}

View File

@ -1,7 +1,7 @@
use r_efi::efi::Status;
use r_efi::efi::protocols::{device_path, loaded_image_device_path};
use super::{RawOsError, helpers, unsupported};
use super::{RawOsError, helpers, unsupported_err};
use crate::error::Error as StdError;
use crate::ffi::{OsStr, OsString};
use crate::marker::PhantomData;
@ -125,11 +125,32 @@ pub fn error_string(errno: RawOsError) -> String {
}
pub fn getcwd() -> io::Result<PathBuf> {
unsupported()
match uefi_shell::open_shell() {
Some(shell) => {
// SAFETY: path_ptr is managed by UEFI shell and should not be deallocated
let path_ptr = unsafe { ((*shell.as_ptr()).get_cur_dir)(crate::ptr::null_mut()) };
helpers::os_string_from_raw(path_ptr)
.map(PathBuf::from)
.ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))
}
None => {
let mut t = current_exe()?;
// SAFETY: This should never fail since the disk prefix will be present even for root
// executables
assert!(t.pop());
Ok(t)
}
}
}
pub fn chdir(_: &path::Path) -> io::Result<()> {
unsupported()
pub fn chdir(p: &path::Path) -> io::Result<()> {
let shell = uefi_shell::open_shell().ok_or(unsupported_err())?;
let mut p = helpers::os_string_to_raw(p.as_os_str())
.ok_or(io::const_io_error!(io::ErrorKind::InvalidData, "Invalid path"))?;
let r = unsafe { ((*shell.as_ptr()).set_cur_dir)(crate::ptr::null_mut(), p.as_mut_ptr()) };
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}
pub struct SplitPaths<'a>(!, PhantomData<&'a ()>);
@ -239,3 +260,37 @@ pub fn exit(code: i32) -> ! {
pub fn getpid() -> u32 {
panic!("no pids on this platform")
}
mod uefi_shell {
use r_efi::protocols::shell;
use super::super::helpers;
use crate::ptr::NonNull;
use crate::sync::atomic::{AtomicPtr, Ordering};
pub fn open_shell() -> Option<NonNull<shell::Protocol>> {
static LAST_VALID_HANDLE: AtomicPtr<crate::ffi::c_void> =
AtomicPtr::new(crate::ptr::null_mut());
if let Some(handle) = NonNull::new(LAST_VALID_HANDLE.load(Ordering::Acquire)) {
if let Ok(protocol) = helpers::open_protocol::<shell::Protocol>(
handle,
r_efi::protocols::shell::PROTOCOL_GUID,
) {
return Some(protocol);
}
}
let handles = helpers::locate_handles(shell::PROTOCOL_GUID).ok()?;
for handle in handles {
if let Ok(protocol) =
helpers::open_protocol::<shell::Protocol>(handle, shell::PROTOCOL_GUID)
{
LAST_VALID_HANDLE.store(handle.as_ptr(), Ordering::Release);
return Some(protocol);
}
}
None
}
}

View File

@ -612,6 +612,9 @@ impl Target {
if triple.contains("-none") || triple.contains("nvptx") || triple.contains("switch") {
target.no_std = true;
}
if triple.contains("emscripten") {
target.runner = Some("node".into());
}
target
}
}

View File

@ -6,7 +6,7 @@ ARM64e tvOS (10.0+)
## Target maintainers
- Artyom Tetyukhin ([@arttet](https://github.com/https://github.com/arttet))
- Artyom Tetyukhin ([@arttet](https://github.com/arttet))
## Requirements

View File

@ -670,11 +670,11 @@ def StdRcSummaryProvider(valobj, dict):
class StdRcSyntheticProvider:
"""Pretty-printer for alloc::rc::Rc<T> and alloc::sync::Arc<T>
struct Rc<T> { ptr: NonNull<RcBox<T>>, ... }
struct Rc<T> { ptr: NonNull<RcInner<T>>, ... }
rust 1.31.1: struct NonNull<T> { pointer: NonZero<*const T> }
rust 1.33.0: struct NonNull<T> { pointer: *const T }
struct NonZero<T>(T)
struct RcBox<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }
struct RcInner<T> { strong: Cell<usize>, weak: Cell<usize>, value: T }
struct Cell<T> { value: UnsafeCell<T> }
struct UnsafeCell<T> { value: T }

View File

@ -95,7 +95,7 @@
<Item Name="[Weak reference count]">ptr.pointer.data_ptr->weak</Item>
<ArrayItems>
<Size>ptr.pointer.length</Size>
<!-- We add +2 to the data_ptr in order to skip the ref count fields in the RcBox -->
<!-- We add +2 to the data_ptr in order to skip the ref count fields in the RcInner -->
<ValuePointer>($T1*)(((size_t*)ptr.pointer.data_ptr) + 2)</ValuePointer>
</ArrayItems>
</Expand>

View File

@ -1643,7 +1643,9 @@ impl<'test> TestCx<'test> {
// double the length.
let mut f = self.output_base_dir().join("a");
// FIXME: This is using the host architecture exe suffix, not target!
if self.config.target.starts_with("wasm") {
if self.config.target.contains("emscripten") {
f = f.with_extra_extension("js");
} else if self.config.target.starts_with("wasm") {
f = f.with_extra_extension("wasm");
} else if self.config.target.contains("spirv") {
f = f.with_extra_extension("spv");

View File

@ -145,20 +145,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(Scalar::from_bool(branch), dest)?;
}
// Floating-point operations
"fabsf32" => {
let [f] = check_arg_count(args)?;
let f = this.read_scalar(f)?.to_f32()?;
// This is a "bitwise" operation, so there's no NaN non-determinism.
this.write_scalar(Scalar::from_f32(f.abs()), dest)?;
}
"fabsf64" => {
let [f] = check_arg_count(args)?;
let f = this.read_scalar(f)?.to_f64()?;
// This is a "bitwise" operation, so there's no NaN non-determinism.
this.write_scalar(Scalar::from_f64(f.abs()), dest)?;
}
"floorf32" | "ceilf32" | "truncf32" | "roundf32" | "rintf32" => {
let [f] = check_arg_count(args)?;
let f = this.read_scalar(f)?.to_f32()?;
@ -249,31 +235,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
this.write_scalar(res, dest)?;
}
"minnumf32" | "maxnumf32" | "copysignf32" => {
let [a, b] = check_arg_count(args)?;
let a = this.read_scalar(a)?.to_f32()?;
let b = this.read_scalar(b)?.to_f32()?;
let res = match intrinsic_name {
"minnumf32" => this.adjust_nan(a.min(b), &[a, b]),
"maxnumf32" => this.adjust_nan(a.max(b), &[a, b]),
"copysignf32" => a.copy_sign(b), // bitwise, no NaN adjustments
_ => bug!(),
};
this.write_scalar(Scalar::from_f32(res), dest)?;
}
"minnumf64" | "maxnumf64" | "copysignf64" => {
let [a, b] = check_arg_count(args)?;
let a = this.read_scalar(a)?.to_f64()?;
let b = this.read_scalar(b)?.to_f64()?;
let res = match intrinsic_name {
"minnumf64" => this.adjust_nan(a.min(b), &[a, b]),
"maxnumf64" => this.adjust_nan(a.max(b), &[a, b]),
"copysignf64" => a.copy_sign(b), // bitwise, no NaN adjustments
_ => bug!(),
};
this.write_scalar(Scalar::from_f64(res), dest)?;
}
"fmaf32" => {
let [a, b, c] = check_arg_count(args)?;
let a = this.read_scalar(a)?.to_f32()?;

View File

@ -115,8 +115,4 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
nan
}
}
fn adjust_nan<F1: Float + FloatConvert<F2>, F2: Float>(&self, f: F2, inputs: &[F1]) -> F2 {
if f.is_nan() { self.generate_nan(inputs) } else { f }
}
}

View File

@ -1,8 +1,8 @@
error: memory leaked: ALLOC (Rust heap, SIZE, ALIGN), allocated here:
--> RUSTLIB/alloc/src/rc.rs:LL:CC
|
LL | Box::leak(Box::new(RcBox { strong: Cell::new(1), weak: Cell::new(1), value }))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | Box::leak(Box::new(RcInner { strong: Cell::new(1), weak: Cell::new(1), value }))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: BACKTRACE:
= note: inside `std::rc::Rc::<std::cell::RefCell<std::option::Option<Dummy>>>::new` at RUSTLIB/alloc/src/rc.rs:LL:CC

View File

@ -1520,7 +1520,6 @@ ui/issues/issue-12567.rs
ui/issues/issue-12612.rs
ui/issues/issue-12660.rs
ui/issues/issue-12677.rs
ui/issues/issue-12699.rs
ui/issues/issue-12729.rs
ui/issues/issue-12744.rs
ui/issues/issue-12860.rs

View File

@ -17,7 +17,7 @@ use ignore::Walk;
const ENTRY_LIMIT: u32 = 901;
// FIXME: The following limits should be reduced eventually.
const ISSUES_ENTRY_LIMIT: u32 = 1673;
const ISSUES_ENTRY_LIMIT: u32 = 1672;
const EXPECTED_TEST_FILE_EXTENSIONS: &[&str] = &[
"rs", // test source files

View File

@ -19,8 +19,7 @@
// gdb-check:$4 = ("Hello", "World")
// gdb-command:print str_in_rc
// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull<alloc::rc::RcBox<&str>> {pointer: 0x[...]}, phantom: core::marker::PhantomData<alloc::rc::RcBox<&str>>, alloc: alloc::alloc::Global}
// gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull<alloc::rc::RcInner<&str>> {pointer: 0x[...]}, phantom: core::marker::PhantomData<alloc::rc::RcInner<&str>>, alloc: alloc::alloc::Global}
// === LLDB TESTS ==================================================================================
// lldb-command:run

View File

@ -160,14 +160,14 @@ mod prelude {
pub struct Box<T: ?Sized, A = Global>(Unique<T>, A);
#[repr(C)]
struct RcBox<T: ?Sized> {
struct RcInner<T: ?Sized> {
strong: UnsafeCell<usize>,
weak: UnsafeCell<usize>,
value: T,
}
pub struct Rc<T: ?Sized, A = Global> {
ptr: NonNull<RcBox<T>>,
phantom: PhantomData<RcBox<T>>,
ptr: NonNull<RcInner<T>>,
phantom: PhantomData<RcInner<T>>,
alloc: A,
}

View File

@ -0,0 +1,47 @@
//@ run-pass
//! Tests the float intrinsics: min, max, abs, copysign
#![feature(const_float_methods)]
#![feature(f16, f128)]
const F16_MIN: f16 = 1.0_f16.min(0.5_f16);
const F16_MAX: f16 = 1.0_f16.max(0.5_f16);
const F16_ABS: f16 = (-1.0_f16).abs();
const F16_COPYSIGN: f16 = 1.0_f16.copysign(-2.0_f16);
const F32_MIN: f32 = 1.0_f32.min(0.5_f32);
const F32_MAX: f32 = 1.0_f32.max(0.5_f32);
const F32_ABS: f32 = (-1.0_f32).abs();
const F32_COPYSIGN: f32 = 1.0_f32.copysign(-2.0_f32);
const F64_MIN: f64 = 1.0_f64.min(0.5_f64);
const F64_MAX: f64 = 1.0_f64.max(0.5_f64);
const F64_ABS: f64 = (-1.0_f64).abs();
const F64_COPYSIGN: f64 = 1.0_f64.copysign(-2.0_f64);
const F128_MIN: f128 = 1.0_f128.min(0.5_f128);
const F128_MAX: f128 = 1.0_f128.max(0.5_f128);
const F128_ABS: f128 = (-1.0_f128).abs();
const F128_COPYSIGN: f128 = 1.0_f128.copysign(-2.0_f128);
fn main() {
assert_eq!(F16_MIN, 0.5);
assert_eq!(F16_MAX, 1.0);
assert_eq!(F16_ABS, 1.0);
assert_eq!(F16_COPYSIGN, -1.0);
assert_eq!(F32_MIN, 0.5);
assert_eq!(F32_MAX, 1.0);
assert_eq!(F32_ABS, 1.0);
assert_eq!(F32_COPYSIGN, -1.0);
assert_eq!(F64_MIN, 0.5);
assert_eq!(F64_MAX, 1.0);
assert_eq!(F64_ABS, 1.0);
assert_eq!(F64_COPYSIGN, -1.0);
assert_eq!(F128_MIN, 0.5);
assert_eq!(F128_MAX, 1.0);
assert_eq!(F128_ABS, 1.0);
assert_eq!(F128_COPYSIGN, -1.0);
}

View File

@ -13,7 +13,6 @@ mod rusti {
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "emscripten",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",

View File

@ -15,11 +15,12 @@
//@ ignore-vxworks no 'sh'
//@ ignore-fuchsia no 'sh'
//@ ignore-emscripten No threads
//@ only-unix SIGPIPE is a unix feature
use std::process;
use std::thread;
#[cfg(unix)]
fn main() {
// Just in case `yes` doesn't check for EPIPE...
thread::spawn(|| {
@ -34,8 +35,3 @@ fn main() {
assert!(output.status.success());
assert!(output.stderr.len() == 0);
}
#[cfg(not(unix))]
fn main() {
// Not worried about signal masks on other platforms
}

View File

@ -1,6 +1,9 @@
//@ run-pass
//@ ignore-sgx not supported
//@ ignore-emscripten
// FIXME: test hangs on emscripten
#![allow(deprecated)]
#![allow(unused_imports)]
use std::thread;

View File

@ -33,7 +33,6 @@ struct Outer {
#[cfg(any(
target_os = "android",
target_os = "dragonfly",
target_os = "emscripten",
target_os = "freebsd",
target_os = "fuchsia",
target_os = "hurd",

View File

@ -0,0 +1,12 @@
#![feature(negative_bounds)]
#[diagnostic::on_unimplemented(message = "this ain't fooing")]
trait Foo {}
struct NotFoo;
fn hello() -> impl !Foo {
//~^ ERROR the trait bound `NotFoo: !Foo` is not satisfied
NotFoo
}
fn main() {}

View File

@ -0,0 +1,18 @@
error[E0277]: the trait bound `NotFoo: !Foo` is not satisfied
--> $DIR/on-unimplemented.rs:7:15
|
LL | fn hello() -> impl !Foo {
| ^^^^^^^^^ the trait bound `NotFoo: !Foo` is not satisfied
LL |
LL | NotFoo
| ------ return type was inferred to be `NotFoo` here
|
help: this trait has no implementations, consider adding one
--> $DIR/on-unimplemented.rs:4:1
|
LL | trait Foo {}
| ^^^^^^^^^
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0277`.