mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-02 18:12:51 +00:00
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:
commit
e7c0d27507
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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)]
|
||||
|
@ -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(())
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
|
@ -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,
|
||||
|
@ -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());
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 doesn’t 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),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 doesn’t 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
|
||||
|
@ -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()
|
||||
//! }
|
||||
|
@ -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) {
|
||||
|
@ -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)]
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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) }
|
||||
}
|
||||
|
||||
|
@ -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)]
|
||||
|
@ -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) }
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 }
|
||||
|
||||
|
@ -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>
|
||||
|
@ -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");
|
||||
|
@ -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()?;
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
47
tests/ui/consts/const-eval/float_methods.rs
Normal file
47
tests/ui/consts/const-eval/float_methods.rs
Normal 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);
|
||||
}
|
@ -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",
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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",
|
||||
|
12
tests/ui/traits/negative-bounds/on-unimplemented.rs
Normal file
12
tests/ui/traits/negative-bounds/on-unimplemented.rs
Normal 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() {}
|
18
tests/ui/traits/negative-bounds/on-unimplemented.stderr
Normal file
18
tests/ui/traits/negative-bounds/on-unimplemented.stderr
Normal 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`.
|
Loading…
Reference in New Issue
Block a user