Auto merge of #135357 - jhpratt:rollup-gs00yt3, r=jhpratt
Rollup of 6 pull requests Successful merges: - #134074 (bootstrap: `std::io::ErrorKind::CrossesDevices` is finally stable) - #135236 (Update a bunch of library types for MCP807) - #135301 (re-add a warning for old master branch, but with much simpler logic) - #135324 (Initial fs module for uefi) - #135326 (support target specific `optimized-compiler-builtins`) - #135347 (Use `NonNull::without_provenance` within the standard library) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
ce55b2052d
30 changed files with 748 additions and 250 deletions
|
@ -922,6 +922,15 @@
|
|||
# argument as the test binary.
|
||||
#runner = <none> (string)
|
||||
|
||||
# Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics
|
||||
# on this target.
|
||||
# Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt`
|
||||
# sources are available.
|
||||
#
|
||||
# Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
|
||||
# order to run `x check`.
|
||||
#optimized-compiler-builtins = build.optimized-compiler-builtins (bool)
|
||||
|
||||
# =============================================================================
|
||||
# Distribution options
|
||||
#
|
||||
|
|
|
@ -126,6 +126,7 @@
|
|||
#![feature(local_waker)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_uninit_array_transpose)]
|
||||
#![feature(nonnull_provenance)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(pattern)]
|
||||
#![feature(pin_coerce_unsized_trait)]
|
||||
|
@ -142,6 +143,7 @@
|
|||
#![feature(slice_range)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(str_internals)]
|
||||
#![feature(temporary_niche_types)]
|
||||
#![feature(trusted_fused)]
|
||||
#![feature(trusted_len)]
|
||||
#![feature(trusted_random_access)]
|
||||
|
|
|
@ -33,21 +33,15 @@ enum AllocInit {
|
|||
Zeroed,
|
||||
}
|
||||
|
||||
#[repr(transparent)]
|
||||
#[cfg_attr(target_pointer_width = "16", rustc_layout_scalar_valid_range_end(0x7fff))]
|
||||
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0x7fff_ffff))]
|
||||
#[cfg_attr(target_pointer_width = "64", rustc_layout_scalar_valid_range_end(0x7fff_ffff_ffff_ffff))]
|
||||
struct Cap(usize);
|
||||
type Cap = core::num::niche_types::UsizeNoHighBit;
|
||||
|
||||
impl Cap {
|
||||
const ZERO: Cap = unsafe { Cap(0) };
|
||||
const ZERO_CAP: Cap = unsafe { Cap::new_unchecked(0) };
|
||||
|
||||
/// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`.
|
||||
///
|
||||
/// # Safety: cap must be <= `isize::MAX`.
|
||||
unsafe fn new<T>(cap: usize) -> Self {
|
||||
if T::IS_ZST { Cap::ZERO } else { unsafe { Self(cap) } }
|
||||
}
|
||||
/// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`.
|
||||
///
|
||||
/// # Safety: cap must be <= `isize::MAX`.
|
||||
unsafe fn new_cap<T>(cap: usize) -> Cap {
|
||||
if T::IS_ZST { ZERO_CAP } else { unsafe { Cap::new_unchecked(cap) } }
|
||||
}
|
||||
|
||||
/// A low-level utility for more ergonomically allocating, reallocating, and deallocating
|
||||
|
@ -257,7 +251,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
// SAFETY: Precondition passed to the caller
|
||||
unsafe {
|
||||
let ptr = ptr.cast();
|
||||
let capacity = Cap::new::<T>(capacity);
|
||||
let capacity = new_cap::<T>(capacity);
|
||||
Self {
|
||||
inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc),
|
||||
_marker: PhantomData,
|
||||
|
@ -275,7 +269,7 @@ impl<T, A: Allocator> RawVec<T, A> {
|
|||
// SAFETY: Precondition passed to the caller
|
||||
unsafe {
|
||||
let ptr = ptr.cast();
|
||||
let capacity = Cap::new::<T>(capacity);
|
||||
let capacity = new_cap::<T>(capacity);
|
||||
Self { inner: RawVecInner::from_nonnull_in(ptr, capacity, alloc), _marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
@ -410,7 +404,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
const fn new_in(alloc: A, align: usize) -> Self {
|
||||
let ptr = unsafe { core::mem::transmute(align) };
|
||||
// `cap: 0` means "unallocated". zero-sized types are ignored.
|
||||
Self { ptr, cap: Cap::ZERO, alloc }
|
||||
Self { ptr, cap: ZERO_CAP, alloc }
|
||||
}
|
||||
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
|
@ -483,7 +477,11 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
// Allocators currently return a `NonNull<[u8]>` whose length
|
||||
// matches the size requested. If that ever changes, the capacity
|
||||
// here should change to `ptr.len() / mem::size_of::<T>()`.
|
||||
Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc })
|
||||
Ok(Self {
|
||||
ptr: Unique::from(ptr.cast()),
|
||||
cap: unsafe { Cap::new_unchecked(capacity) },
|
||||
alloc,
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -508,7 +506,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
|
||||
#[inline]
|
||||
const fn capacity(&self, elem_size: usize) -> usize {
|
||||
if elem_size == 0 { usize::MAX } else { self.cap.0 }
|
||||
if elem_size == 0 { usize::MAX } else { self.cap.as_inner() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -518,7 +516,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
|
||||
#[inline]
|
||||
fn current_memory(&self, elem_layout: Layout) -> Option<(NonNull<u8>, Layout)> {
|
||||
if elem_layout.size() == 0 || self.cap.0 == 0 {
|
||||
if elem_layout.size() == 0 || self.cap.as_inner() == 0 {
|
||||
None
|
||||
} else {
|
||||
// We could use Layout::array here which ensures the absence of isize and usize overflows
|
||||
|
@ -526,7 +524,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
// has already been allocated so we know it can't overflow and currently Rust does not
|
||||
// support such types. So we can do better by skipping some checks and avoid an unwrap.
|
||||
unsafe {
|
||||
let alloc_size = elem_layout.size().unchecked_mul(self.cap.0);
|
||||
let alloc_size = elem_layout.size().unchecked_mul(self.cap.as_inner());
|
||||
let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align());
|
||||
Some((self.ptr.into(), layout))
|
||||
}
|
||||
|
@ -562,7 +560,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
#[inline]
|
||||
#[track_caller]
|
||||
fn grow_one(&mut self, elem_layout: Layout) {
|
||||
if let Err(err) = self.grow_amortized(self.cap.0, 1, elem_layout) {
|
||||
if let Err(err) = self.grow_amortized(self.cap.as_inner(), 1, elem_layout) {
|
||||
handle_error(err);
|
||||
}
|
||||
}
|
||||
|
@ -627,7 +625,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
// the size requested. If that ever changes, the capacity here should
|
||||
// change to `ptr.len() / mem::size_of::<T>()`.
|
||||
self.ptr = Unique::from(ptr.cast());
|
||||
self.cap = unsafe { Cap(cap) };
|
||||
self.cap = unsafe { Cap::new_unchecked(cap) };
|
||||
}
|
||||
|
||||
fn grow_amortized(
|
||||
|
@ -650,7 +648,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
|
||||
// This guarantees exponential growth. The doubling cannot overflow
|
||||
// because `cap <= isize::MAX` and the type of `cap` is `usize`.
|
||||
let cap = cmp::max(self.cap.0 * 2, required_cap);
|
||||
let cap = cmp::max(self.cap.as_inner() * 2, required_cap);
|
||||
let cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap);
|
||||
|
||||
let new_layout = layout_array(cap, elem_layout)?;
|
||||
|
@ -719,7 +717,7 @@ impl<A: Allocator> RawVecInner<A> {
|
|||
unsafe { self.alloc.deallocate(ptr, layout) };
|
||||
self.ptr =
|
||||
unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) };
|
||||
self.cap = Cap::ZERO;
|
||||
self.cap = ZERO_CAP;
|
||||
} else {
|
||||
let ptr = unsafe {
|
||||
// Layout cannot overflow here because it would have
|
||||
|
|
|
@ -252,6 +252,7 @@ use core::intrinsics::abort;
|
|||
use core::iter;
|
||||
use core::marker::{PhantomData, Unsize};
|
||||
use core::mem::{self, ManuallyDrop, align_of_val_raw};
|
||||
use core::num::NonZeroUsize;
|
||||
use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
|
||||
use core::panic::{RefUnwindSafe, UnwindSafe};
|
||||
#[cfg(not(no_global_oom_handling))]
|
||||
|
@ -3027,12 +3028,7 @@ impl<T> Weak<T> {
|
|||
#[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")]
|
||||
#[must_use]
|
||||
pub const fn new() -> Weak<T> {
|
||||
Weak {
|
||||
ptr: unsafe {
|
||||
NonNull::new_unchecked(ptr::without_provenance_mut::<RcInner<T>>(usize::MAX))
|
||||
},
|
||||
alloc: Global,
|
||||
}
|
||||
Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc: Global }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3054,12 +3050,7 @@ impl<T, A: Allocator> Weak<T, A> {
|
|||
#[inline]
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
pub fn new_in(alloc: A) -> Weak<T, A> {
|
||||
Weak {
|
||||
ptr: unsafe {
|
||||
NonNull::new_unchecked(ptr::without_provenance_mut::<RcInner<T>>(usize::MAX))
|
||||
},
|
||||
alloc,
|
||||
}
|
||||
Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ use core::intrinsics::abort;
|
|||
use core::iter;
|
||||
use core::marker::{PhantomData, Unsize};
|
||||
use core::mem::{self, ManuallyDrop, align_of_val_raw};
|
||||
use core::num::NonZeroUsize;
|
||||
use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver};
|
||||
use core::panic::{RefUnwindSafe, UnwindSafe};
|
||||
use core::pin::{Pin, PinCoerceUnsized};
|
||||
|
@ -2687,12 +2688,7 @@ impl<T> Weak<T> {
|
|||
#[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")]
|
||||
#[must_use]
|
||||
pub const fn new() -> Weak<T> {
|
||||
Weak {
|
||||
ptr: unsafe {
|
||||
NonNull::new_unchecked(ptr::without_provenance_mut::<ArcInner<T>>(usize::MAX))
|
||||
},
|
||||
alloc: Global,
|
||||
}
|
||||
Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc: Global }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2717,12 +2713,7 @@ impl<T, A: Allocator> Weak<T, A> {
|
|||
#[inline]
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
pub fn new_in(alloc: A) -> Weak<T, A> {
|
||||
Weak {
|
||||
ptr: unsafe {
|
||||
NonNull::new_unchecked(ptr::without_provenance_mut::<ArcInner<T>>(usize::MAX))
|
||||
},
|
||||
alloc,
|
||||
}
|
||||
Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -233,8 +233,7 @@ impl Layout {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn dangling(&self) -> NonNull<u8> {
|
||||
// SAFETY: align is guaranteed to be non-zero
|
||||
unsafe { NonNull::new_unchecked(crate::ptr::without_provenance_mut::<u8>(self.align())) }
|
||||
NonNull::without_provenance(self.align.as_nonzero())
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record that can hold a value
|
||||
|
|
|
@ -51,6 +51,10 @@ mod overflow_panic;
|
|||
mod saturating;
|
||||
mod wrapping;
|
||||
|
||||
/// 100% perma-unstable
|
||||
#[doc(hidden)]
|
||||
pub mod niche_types;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg(not(no_fp_fmt_parse))]
|
||||
pub use dec2flt::ParseFloatError;
|
||||
|
|
168
library/core/src/num/niche_types.rs
Normal file
168
library/core/src/num/niche_types.rs
Normal file
|
@ -0,0 +1,168 @@
|
|||
#![unstable(
|
||||
feature = "temporary_niche_types",
|
||||
issue = "none",
|
||||
reason = "for core, alloc, and std internals until pattern types are further along"
|
||||
)]
|
||||
|
||||
use crate::cmp::Ordering;
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::marker::StructuralPartialEq;
|
||||
|
||||
macro_rules! define_valid_range_type {
|
||||
($(
|
||||
$(#[$m:meta])*
|
||||
$vis:vis struct $name:ident($int:ident as $uint:ident in $low:literal..=$high:literal);
|
||||
)+) => {$(
|
||||
#[derive(Clone, Copy, Eq)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start($low)]
|
||||
#[rustc_layout_scalar_valid_range_end($high)]
|
||||
$(#[$m])*
|
||||
$vis struct $name($int);
|
||||
|
||||
const _: () = {
|
||||
// With the `valid_range` attributes, it's always specified as unsigned
|
||||
assert!(<$uint>::MIN == 0);
|
||||
let ulow: $uint = $low;
|
||||
let uhigh: $uint = $high;
|
||||
assert!(ulow <= uhigh);
|
||||
|
||||
assert!(size_of::<$int>() == size_of::<$uint>());
|
||||
};
|
||||
|
||||
impl $name {
|
||||
/// Constructs an instance of this type from the underlying integer
|
||||
/// primitive without checking whether its zero.
|
||||
///
|
||||
/// # Safety
|
||||
/// Immediate language UB if `val == 0`, as it violates the validity
|
||||
/// invariant of this type.
|
||||
#[inline]
|
||||
pub const unsafe fn new_unchecked(val: $int) -> Self {
|
||||
// SAFETY: Caller promised that `val` is non-zero.
|
||||
unsafe { $name(val) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn as_inner(self) -> $int {
|
||||
// SAFETY: This is a transparent wrapper, so unwrapping it is sound
|
||||
// (Not using `.0` due to MCP#807.)
|
||||
unsafe { crate::mem::transmute(self) }
|
||||
}
|
||||
}
|
||||
|
||||
// This is required to allow matching a constant. We don't get it from a derive
|
||||
// because the derived `PartialEq` would do a field projection, which is banned
|
||||
// by <https://github.com/rust-lang/compiler-team/issues/807>.
|
||||
impl StructuralPartialEq for $name {}
|
||||
|
||||
impl PartialEq for $name {
|
||||
#[inline]
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.as_inner() == other.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for $name {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &Self) -> Ordering {
|
||||
Ord::cmp(&self.as_inner(), &other.as_inner())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for $name {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||
Some(Ord::cmp(self, other))
|
||||
}
|
||||
}
|
||||
|
||||
impl Hash for $name {
|
||||
// Required method
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
Hash::hash(&self.as_inner(), state);
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
<$int as fmt::Debug>::fmt(&self.as_inner(), f)
|
||||
}
|
||||
}
|
||||
)+};
|
||||
}
|
||||
|
||||
define_valid_range_type! {
|
||||
pub struct Nanoseconds(u32 as u32 in 0..=999_999_999);
|
||||
}
|
||||
|
||||
impl Nanoseconds {
|
||||
// SAFETY: 0 is within the valid range
|
||||
pub const ZERO: Self = unsafe { Nanoseconds::new_unchecked(0) };
|
||||
}
|
||||
|
||||
impl Default for Nanoseconds {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::ZERO
|
||||
}
|
||||
}
|
||||
|
||||
define_valid_range_type! {
|
||||
pub struct NonZeroU8Inner(u8 as u8 in 1..=0xff);
|
||||
pub struct NonZeroU16Inner(u16 as u16 in 1..=0xff_ff);
|
||||
pub struct NonZeroU32Inner(u32 as u32 in 1..=0xffff_ffff);
|
||||
pub struct NonZeroU64Inner(u64 as u64 in 1..=0xffffffff_ffffffff);
|
||||
pub struct NonZeroU128Inner(u128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff);
|
||||
|
||||
pub struct NonZeroI8Inner(i8 as u8 in 1..=0xff);
|
||||
pub struct NonZeroI16Inner(i16 as u16 in 1..=0xff_ff);
|
||||
pub struct NonZeroI32Inner(i32 as u32 in 1..=0xffff_ffff);
|
||||
pub struct NonZeroI64Inner(i64 as u64 in 1..=0xffffffff_ffffffff);
|
||||
pub struct NonZeroI128Inner(i128 as u128 in 1..=0xffffffffffffffff_ffffffffffffffff);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
define_valid_range_type! {
|
||||
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff);
|
||||
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff);
|
||||
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff);
|
||||
}
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
define_valid_range_type! {
|
||||
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff);
|
||||
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff);
|
||||
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff);
|
||||
}
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
define_valid_range_type! {
|
||||
pub struct UsizeNoHighBit(usize as usize in 0..=0x7fff_ffff_ffff_ffff);
|
||||
pub struct NonZeroUsizeInner(usize as usize in 1..=0xffff_ffff_ffff_ffff);
|
||||
pub struct NonZeroIsizeInner(isize as usize in 1..=0xffff_ffff_ffff_ffff);
|
||||
}
|
||||
|
||||
define_valid_range_type! {
|
||||
pub struct U32NotAllOnes(u32 as u32 in 0..=0xffff_fffe);
|
||||
pub struct I32NotAllOnes(i32 as u32 in 0..=0xffff_fffe);
|
||||
|
||||
pub struct U64NotAllOnes(u64 as u64 in 0..=0xffff_ffff_ffff_fffe);
|
||||
pub struct I64NotAllOnes(i64 as u64 in 0..=0xffff_ffff_ffff_fffe);
|
||||
}
|
||||
|
||||
pub trait NotAllOnesHelper {
|
||||
type Type;
|
||||
}
|
||||
pub type NotAllOnes<T> = <T as NotAllOnesHelper>::Type;
|
||||
impl NotAllOnesHelper for u32 {
|
||||
type Type = U32NotAllOnes;
|
||||
}
|
||||
impl NotAllOnesHelper for i32 {
|
||||
type Type = I32NotAllOnes;
|
||||
}
|
||||
impl NotAllOnesHelper for u64 {
|
||||
type Type = U64NotAllOnes;
|
||||
}
|
||||
impl NotAllOnesHelper for i64 {
|
||||
type Type = I64NotAllOnes;
|
||||
}
|
|
@ -37,41 +37,12 @@ pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed {
|
|||
macro_rules! impl_zeroable_primitive {
|
||||
($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => {
|
||||
mod private {
|
||||
use super::*;
|
||||
|
||||
#[unstable(
|
||||
feature = "nonzero_internals",
|
||||
reason = "implementation detail which may disappear or be replaced at any time",
|
||||
issue = "none"
|
||||
)]
|
||||
pub trait Sealed {}
|
||||
|
||||
$(
|
||||
// This inner type is never shown directly, so intentionally does not have Debug
|
||||
#[expect(missing_debug_implementations)]
|
||||
// Since this struct is non-generic and derives Copy,
|
||||
// the derived Clone is `*self` and thus doesn't field-project.
|
||||
#[derive(Clone, Copy)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(1)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
#[unstable(
|
||||
feature = "nonzero_internals",
|
||||
reason = "implementation detail which may disappear or be replaced at any time",
|
||||
issue = "none"
|
||||
)]
|
||||
pub struct $NonZeroInner($primitive);
|
||||
|
||||
// This is required to allow matching a constant. We don't get it from a derive
|
||||
// because the derived `PartialEq` would do a field projection, which is banned
|
||||
// by <https://github.com/rust-lang/compiler-team/issues/807>.
|
||||
#[unstable(
|
||||
feature = "nonzero_internals",
|
||||
reason = "implementation detail which may disappear or be replaced at any time",
|
||||
issue = "none"
|
||||
)]
|
||||
impl StructuralPartialEq for $NonZeroInner {}
|
||||
)+
|
||||
}
|
||||
|
||||
$(
|
||||
|
@ -88,7 +59,7 @@ macro_rules! impl_zeroable_primitive {
|
|||
issue = "none"
|
||||
)]
|
||||
unsafe impl ZeroablePrimitive for $primitive {
|
||||
type NonZeroInner = private::$NonZeroInner;
|
||||
type NonZeroInner = super::niche_types::$NonZeroInner;
|
||||
}
|
||||
)+
|
||||
};
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
use crate::fmt;
|
||||
use crate::iter::Sum;
|
||||
use crate::num::niche_types::Nanoseconds;
|
||||
use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
|
||||
|
||||
const NANOS_PER_SEC: u32 = 1_000_000_000;
|
||||
|
@ -37,24 +38,6 @@ const HOURS_PER_DAY: u64 = 24;
|
|||
#[unstable(feature = "duration_units", issue = "120301")]
|
||||
const DAYS_PER_WEEK: u64 = 7;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
#[rustc_layout_scalar_valid_range_end(999_999_999)]
|
||||
struct Nanoseconds(u32);
|
||||
|
||||
impl Nanoseconds {
|
||||
// SAFETY: 0 is within the valid range
|
||||
const ZERO: Self = unsafe { Nanoseconds(0) };
|
||||
}
|
||||
|
||||
impl Default for Nanoseconds {
|
||||
#[inline]
|
||||
fn default() -> Self {
|
||||
Self::ZERO
|
||||
}
|
||||
}
|
||||
|
||||
/// A `Duration` type to represent a span of time, typically used for system
|
||||
/// timeouts.
|
||||
///
|
||||
|
@ -211,14 +194,14 @@ impl Duration {
|
|||
pub const fn new(secs: u64, nanos: u32) -> Duration {
|
||||
if nanos < NANOS_PER_SEC {
|
||||
// SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range
|
||||
Duration { secs, nanos: unsafe { Nanoseconds(nanos) } }
|
||||
Duration { secs, nanos: unsafe { Nanoseconds::new_unchecked(nanos) } }
|
||||
} else {
|
||||
let secs = secs
|
||||
.checked_add((nanos / NANOS_PER_SEC) as u64)
|
||||
.expect("overflow in Duration::new");
|
||||
let nanos = nanos % NANOS_PER_SEC;
|
||||
// SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range
|
||||
Duration { secs, nanos: unsafe { Nanoseconds(nanos) } }
|
||||
Duration { secs, nanos: unsafe { Nanoseconds::new_unchecked(nanos) } }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -263,7 +246,7 @@ impl Duration {
|
|||
let subsec_millis = (millis % MILLIS_PER_SEC) as u32;
|
||||
// SAFETY: (x % 1_000) * 1_000_000 < 1_000_000_000
|
||||
// => x % 1_000 < 1_000
|
||||
let subsec_nanos = unsafe { Nanoseconds(subsec_millis * NANOS_PER_MILLI) };
|
||||
let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_millis * NANOS_PER_MILLI) };
|
||||
|
||||
Duration { secs, nanos: subsec_nanos }
|
||||
}
|
||||
|
@ -289,7 +272,7 @@ impl Duration {
|
|||
let subsec_micros = (micros % MICROS_PER_SEC) as u32;
|
||||
// SAFETY: (x % 1_000_000) * 1_000 < 1_000_000_000
|
||||
// => x % 1_000_000 < 1_000_000
|
||||
let subsec_nanos = unsafe { Nanoseconds(subsec_micros * NANOS_PER_MICRO) };
|
||||
let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_micros * NANOS_PER_MICRO) };
|
||||
|
||||
Duration { secs, nanos: subsec_nanos }
|
||||
}
|
||||
|
@ -320,7 +303,7 @@ impl Duration {
|
|||
let secs = nanos / NANOS_PER_SEC;
|
||||
let subsec_nanos = (nanos % NANOS_PER_SEC) as u32;
|
||||
// SAFETY: x % 1_000_000_000 < 1_000_000_000
|
||||
let subsec_nanos = unsafe { Nanoseconds(subsec_nanos) };
|
||||
let subsec_nanos = unsafe { Nanoseconds::new_unchecked(subsec_nanos) };
|
||||
|
||||
Duration { secs, nanos: subsec_nanos }
|
||||
}
|
||||
|
@ -458,7 +441,7 @@ impl Duration {
|
|||
#[rustc_const_stable(feature = "duration_zero", since = "1.53.0")]
|
||||
#[inline]
|
||||
pub const fn is_zero(&self) -> bool {
|
||||
self.secs == 0 && self.nanos.0 == 0
|
||||
self.secs == 0 && self.nanos.as_inner() == 0
|
||||
}
|
||||
|
||||
/// Returns the number of _whole_ seconds contained by this `Duration`.
|
||||
|
@ -509,7 +492,7 @@ impl Duration {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn subsec_millis(&self) -> u32 {
|
||||
self.nanos.0 / NANOS_PER_MILLI
|
||||
self.nanos.as_inner() / NANOS_PER_MILLI
|
||||
}
|
||||
|
||||
/// Returns the fractional part of this `Duration`, in whole microseconds.
|
||||
|
@ -532,7 +515,7 @@ impl Duration {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn subsec_micros(&self) -> u32 {
|
||||
self.nanos.0 / NANOS_PER_MICRO
|
||||
self.nanos.as_inner() / NANOS_PER_MICRO
|
||||
}
|
||||
|
||||
/// Returns the fractional part of this `Duration`, in nanoseconds.
|
||||
|
@ -555,7 +538,7 @@ impl Duration {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn subsec_nanos(&self) -> u32 {
|
||||
self.nanos.0
|
||||
self.nanos.as_inner()
|
||||
}
|
||||
|
||||
/// Returns the total number of whole milliseconds contained by this `Duration`.
|
||||
|
@ -573,7 +556,8 @@ impl Duration {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn as_millis(&self) -> u128 {
|
||||
self.secs as u128 * MILLIS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MILLI) as u128
|
||||
self.secs as u128 * MILLIS_PER_SEC as u128
|
||||
+ (self.nanos.as_inner() / NANOS_PER_MILLI) as u128
|
||||
}
|
||||
|
||||
/// Returns the total number of whole microseconds contained by this `Duration`.
|
||||
|
@ -591,7 +575,8 @@ impl Duration {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn as_micros(&self) -> u128 {
|
||||
self.secs as u128 * MICROS_PER_SEC as u128 + (self.nanos.0 / NANOS_PER_MICRO) as u128
|
||||
self.secs as u128 * MICROS_PER_SEC as u128
|
||||
+ (self.nanos.as_inner() / NANOS_PER_MICRO) as u128
|
||||
}
|
||||
|
||||
/// Returns the total number of nanoseconds contained by this `Duration`.
|
||||
|
@ -609,7 +594,7 @@ impl Duration {
|
|||
#[must_use]
|
||||
#[inline]
|
||||
pub const fn as_nanos(&self) -> u128 {
|
||||
self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.0 as u128
|
||||
self.secs as u128 * NANOS_PER_SEC as u128 + self.nanos.as_inner() as u128
|
||||
}
|
||||
|
||||
/// Computes the absolute difference between `self` and `other`.
|
||||
|
@ -649,7 +634,7 @@ impl Duration {
|
|||
#[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
|
||||
pub const fn checked_add(self, rhs: Duration) -> Option<Duration> {
|
||||
if let Some(mut secs) = self.secs.checked_add(rhs.secs) {
|
||||
let mut nanos = self.nanos.0 + rhs.nanos.0;
|
||||
let mut nanos = self.nanos.as_inner() + rhs.nanos.as_inner();
|
||||
if nanos >= NANOS_PER_SEC {
|
||||
nanos -= NANOS_PER_SEC;
|
||||
if let Some(new_secs) = secs.checked_add(1) {
|
||||
|
@ -707,11 +692,11 @@ impl Duration {
|
|||
#[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
|
||||
pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> {
|
||||
if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
|
||||
let nanos = if self.nanos.0 >= rhs.nanos.0 {
|
||||
self.nanos.0 - rhs.nanos.0
|
||||
let nanos = if self.nanos.as_inner() >= rhs.nanos.as_inner() {
|
||||
self.nanos.as_inner() - rhs.nanos.as_inner()
|
||||
} else if let Some(sub_secs) = secs.checked_sub(1) {
|
||||
secs = sub_secs;
|
||||
self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0
|
||||
self.nanos.as_inner() + NANOS_PER_SEC - rhs.nanos.as_inner()
|
||||
} else {
|
||||
return None;
|
||||
};
|
||||
|
@ -763,7 +748,7 @@ impl Duration {
|
|||
#[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
|
||||
pub const fn checked_mul(self, rhs: u32) -> Option<Duration> {
|
||||
// Multiply nanoseconds as u64, because it cannot overflow that way.
|
||||
let total_nanos = self.nanos.0 as u64 * rhs as u64;
|
||||
let total_nanos = self.nanos.as_inner() as u64 * rhs as u64;
|
||||
let extra_secs = total_nanos / (NANOS_PER_SEC as u64);
|
||||
let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
|
||||
// FIXME(const-hack): use `and_then` once that is possible.
|
||||
|
@ -820,7 +805,8 @@ impl Duration {
|
|||
pub const fn checked_div(self, rhs: u32) -> Option<Duration> {
|
||||
if rhs != 0 {
|
||||
let (secs, extra_secs) = (self.secs / (rhs as u64), self.secs % (rhs as u64));
|
||||
let (mut nanos, extra_nanos) = (self.nanos.0 / rhs, self.nanos.0 % rhs);
|
||||
let (mut nanos, extra_nanos) =
|
||||
(self.nanos.as_inner() / rhs, self.nanos.as_inner() % rhs);
|
||||
nanos +=
|
||||
((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32;
|
||||
debug_assert!(nanos < NANOS_PER_SEC);
|
||||
|
@ -846,7 +832,7 @@ impl Duration {
|
|||
#[inline]
|
||||
#[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")]
|
||||
pub const fn as_secs_f64(&self) -> f64 {
|
||||
(self.secs as f64) + (self.nanos.0 as f64) / (NANOS_PER_SEC as f64)
|
||||
(self.secs as f64) + (self.nanos.as_inner() as f64) / (NANOS_PER_SEC as f64)
|
||||
}
|
||||
|
||||
/// Returns the number of seconds contained by this `Duration` as `f32`.
|
||||
|
@ -865,7 +851,7 @@ impl Duration {
|
|||
#[inline]
|
||||
#[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")]
|
||||
pub const fn as_secs_f32(&self) -> f32 {
|
||||
(self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32)
|
||||
(self.secs as f32) + (self.nanos.as_inner() as f32) / (NANOS_PER_SEC as f32)
|
||||
}
|
||||
|
||||
/// Returns the number of milliseconds contained by this `Duration` as `f64`.
|
||||
|
@ -885,7 +871,7 @@ impl Duration {
|
|||
#[inline]
|
||||
pub const fn as_millis_f64(&self) -> f64 {
|
||||
(self.secs as f64) * (MILLIS_PER_SEC as f64)
|
||||
+ (self.nanos.0 as f64) / (NANOS_PER_MILLI as f64)
|
||||
+ (self.nanos.as_inner() as f64) / (NANOS_PER_MILLI as f64)
|
||||
}
|
||||
|
||||
/// Returns the number of milliseconds contained by this `Duration` as `f32`.
|
||||
|
@ -905,7 +891,7 @@ impl Duration {
|
|||
#[inline]
|
||||
pub const fn as_millis_f32(&self) -> f32 {
|
||||
(self.secs as f32) * (MILLIS_PER_SEC as f32)
|
||||
+ (self.nanos.0 as f32) / (NANOS_PER_MILLI as f32)
|
||||
+ (self.nanos.as_inner() as f32) / (NANOS_PER_MILLI as f32)
|
||||
}
|
||||
|
||||
/// Creates a new `Duration` from the specified number of seconds represented
|
||||
|
@ -1084,8 +1070,9 @@ impl Duration {
|
|||
#[inline]
|
||||
#[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")]
|
||||
pub const fn div_duration_f64(self, rhs: Duration) -> f64 {
|
||||
let self_nanos = (self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.0 as f64);
|
||||
let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64);
|
||||
let self_nanos =
|
||||
(self.secs as f64) * (NANOS_PER_SEC as f64) + (self.nanos.as_inner() as f64);
|
||||
let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.as_inner() as f64);
|
||||
self_nanos / rhs_nanos
|
||||
}
|
||||
|
||||
|
@ -1105,8 +1092,9 @@ impl Duration {
|
|||
#[inline]
|
||||
#[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")]
|
||||
pub const fn div_duration_f32(self, rhs: Duration) -> f32 {
|
||||
let self_nanos = (self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.0 as f32);
|
||||
let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32);
|
||||
let self_nanos =
|
||||
(self.secs as f32) * (NANOS_PER_SEC as f32) + (self.nanos.as_inner() as f32);
|
||||
let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.as_inner() as f32);
|
||||
self_nanos / rhs_nanos
|
||||
}
|
||||
}
|
||||
|
@ -1201,13 +1189,13 @@ macro_rules! sum_durations {
|
|||
for entry in $iter {
|
||||
total_secs =
|
||||
total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations");
|
||||
total_nanos = match total_nanos.checked_add(entry.nanos.0 as u64) {
|
||||
total_nanos = match total_nanos.checked_add(entry.nanos.as_inner() as u64) {
|
||||
Some(n) => n,
|
||||
None => {
|
||||
total_secs = total_secs
|
||||
.checked_add(total_nanos / NANOS_PER_SEC as u64)
|
||||
.expect("overflow in iter::sum over durations");
|
||||
(total_nanos % NANOS_PER_SEC as u64) + entry.nanos.0 as u64
|
||||
(total_nanos % NANOS_PER_SEC as u64) + entry.nanos.as_inner() as u64
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -1399,27 +1387,27 @@ impl fmt::Debug for Duration {
|
|||
let prefix = if f.sign_plus() { "+" } else { "" };
|
||||
|
||||
if self.secs > 0 {
|
||||
fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s")
|
||||
} else if self.nanos.0 >= NANOS_PER_MILLI {
|
||||
fmt_decimal(f, self.secs, self.nanos.as_inner(), NANOS_PER_SEC / 10, prefix, "s")
|
||||
} else if self.nanos.as_inner() >= NANOS_PER_MILLI {
|
||||
fmt_decimal(
|
||||
f,
|
||||
(self.nanos.0 / NANOS_PER_MILLI) as u64,
|
||||
self.nanos.0 % NANOS_PER_MILLI,
|
||||
(self.nanos.as_inner() / NANOS_PER_MILLI) as u64,
|
||||
self.nanos.as_inner() % NANOS_PER_MILLI,
|
||||
NANOS_PER_MILLI / 10,
|
||||
prefix,
|
||||
"ms",
|
||||
)
|
||||
} else if self.nanos.0 >= NANOS_PER_MICRO {
|
||||
} else if self.nanos.as_inner() >= NANOS_PER_MICRO {
|
||||
fmt_decimal(
|
||||
f,
|
||||
(self.nanos.0 / NANOS_PER_MICRO) as u64,
|
||||
self.nanos.0 % NANOS_PER_MICRO,
|
||||
(self.nanos.as_inner() / NANOS_PER_MICRO) as u64,
|
||||
self.nanos.as_inner() % NANOS_PER_MICRO,
|
||||
NANOS_PER_MICRO / 10,
|
||||
prefix,
|
||||
"µs",
|
||||
)
|
||||
} else {
|
||||
fmt_decimal(f, self.nanos.0 as u64, 0, 1, prefix, "ns")
|
||||
fmt_decimal(f, self.nanos.as_inner() as u64, 0, 1, prefix, "ns")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -103,7 +103,8 @@
|
|||
//! the time.
|
||||
|
||||
use core::marker::PhantomData;
|
||||
use core::ptr::{self, NonNull};
|
||||
use core::num::NonZeroUsize;
|
||||
use core::ptr::NonNull;
|
||||
|
||||
use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
|
||||
|
||||
|
@ -176,7 +177,7 @@ impl Repr {
|
|||
let utagged = ((code as usize) << 32) | TAG_OS;
|
||||
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
|
||||
let res = Self(
|
||||
unsafe { NonNull::new_unchecked(ptr::without_provenance_mut(utagged)) },
|
||||
NonNull::without_provenance(unsafe { NonZeroUsize::new_unchecked(utagged) }),
|
||||
PhantomData,
|
||||
);
|
||||
// quickly smoke-check we encoded the right thing (This generally will
|
||||
|
@ -193,7 +194,7 @@ impl Repr {
|
|||
let utagged = ((kind as usize) << 32) | TAG_SIMPLE;
|
||||
// Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0.
|
||||
let res = Self(
|
||||
unsafe { NonNull::new_unchecked(ptr::without_provenance_mut(utagged)) },
|
||||
NonNull::without_provenance(unsafe { NonZeroUsize::new_unchecked(utagged) }),
|
||||
PhantomData,
|
||||
);
|
||||
// quickly smoke-check we encoded the right thing (This generally will
|
||||
|
|
|
@ -342,6 +342,7 @@
|
|||
#![feature(lazy_get)]
|
||||
#![feature(maybe_uninit_slice)]
|
||||
#![feature(maybe_uninit_write_slice)]
|
||||
#![feature(nonnull_provenance)]
|
||||
#![feature(panic_can_unwind)]
|
||||
#![feature(panic_internals)]
|
||||
#![feature(pin_coerce_unsized_trait)]
|
||||
|
@ -357,6 +358,7 @@
|
|||
#![feature(str_internals)]
|
||||
#![feature(strict_provenance_atomic_ptr)]
|
||||
#![feature(sync_unsafe_cell)]
|
||||
#![feature(temporary_niche_types)]
|
||||
#![feature(ub_checks)]
|
||||
#![feature(used_with_arg)]
|
||||
// tidy-alphabetical-end
|
||||
|
|
|
@ -11,6 +11,8 @@ use crate::sys::cvt;
|
|||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||
use crate::{fmt, fs, io};
|
||||
|
||||
type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>;
|
||||
|
||||
/// A borrowed file descriptor.
|
||||
///
|
||||
/// This has a lifetime parameter to tie it to the lifetime of something that owns the file
|
||||
|
@ -32,15 +34,10 @@ use crate::{fmt, fs, io};
|
|||
/// instead, but this is not supported on all platforms.
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
|
||||
// 32-bit c_int. Below is -2, in two's complement, but that only works out
|
||||
// because c_int is 32 bits.
|
||||
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||
pub struct BorrowedFd<'fd> {
|
||||
fd: RawFd,
|
||||
fd: ValidRawFd,
|
||||
_phantom: PhantomData<&'fd OwnedFd>,
|
||||
}
|
||||
|
||||
|
@ -56,15 +53,10 @@ pub struct BorrowedFd<'fd> {
|
|||
///
|
||||
/// You can use [`AsFd::as_fd`] to obtain a [`BorrowedFd`].
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
|
||||
// 32-bit c_int. Below is -2, in two's complement, but that only works out
|
||||
// because c_int is 32 bits.
|
||||
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||
pub struct OwnedFd {
|
||||
fd: RawFd,
|
||||
fd: ValidRawFd,
|
||||
}
|
||||
|
||||
impl BorrowedFd<'_> {
|
||||
|
@ -80,7 +72,8 @@ impl BorrowedFd<'_> {
|
|||
pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
|
||||
assert!(fd != u32::MAX as RawFd);
|
||||
// SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
|
||||
unsafe { Self { fd, _phantom: PhantomData } }
|
||||
let fd = unsafe { ValidRawFd::new_unchecked(fd) };
|
||||
Self { fd, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,7 +123,7 @@ impl BorrowedFd<'_> {
|
|||
impl AsRawFd for BorrowedFd<'_> {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
self.fd.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +131,7 @@ impl AsRawFd for BorrowedFd<'_> {
|
|||
impl AsRawFd for OwnedFd {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
self.fd.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +139,7 @@ impl AsRawFd for OwnedFd {
|
|||
impl IntoRawFd for OwnedFd {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
ManuallyDrop::new(self).fd
|
||||
ManuallyDrop::new(self).fd.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -164,7 +157,8 @@ impl FromRawFd for OwnedFd {
|
|||
unsafe fn from_raw_fd(fd: RawFd) -> Self {
|
||||
assert_ne!(fd, u32::MAX as RawFd);
|
||||
// SAFETY: we just asserted that the value is in the valid range and isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
|
||||
unsafe { Self { fd } }
|
||||
let fd = unsafe { ValidRawFd::new_unchecked(fd) };
|
||||
Self { fd }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,12 +181,12 @@ impl Drop for OwnedFd {
|
|||
#[cfg(not(target_os = "hermit"))]
|
||||
{
|
||||
#[cfg(unix)]
|
||||
crate::sys::fs::debug_assert_fd_is_open(self.fd);
|
||||
crate::sys::fs::debug_assert_fd_is_open(self.fd.as_inner());
|
||||
|
||||
let _ = libc::close(self.fd);
|
||||
let _ = libc::close(self.fd.as_inner());
|
||||
}
|
||||
#[cfg(target_os = "hermit")]
|
||||
let _ = hermit_abi::close(self.fd);
|
||||
let _ = hermit_abi::close(self.fd.as_inner());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,6 +54,9 @@ use crate::{fmt, net, sys};
|
|||
/// Raw file descriptors.
|
||||
pub type RawFd = i32;
|
||||
|
||||
// The max of this is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
|
||||
type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>;
|
||||
|
||||
/// A borrowed SOLID Sockets file descriptor.
|
||||
///
|
||||
/// This has a lifetime parameter to tie it to the lifetime of something that
|
||||
|
@ -69,12 +72,9 @@ pub type RawFd = i32;
|
|||
/// socket, which is then borrowed under the same lifetime.
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
|
||||
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
pub struct BorrowedFd<'socket> {
|
||||
fd: RawFd,
|
||||
fd: ValidRawFd,
|
||||
_phantom: PhantomData<&'socket OwnedFd>,
|
||||
}
|
||||
|
||||
|
@ -87,12 +87,9 @@ pub struct BorrowedFd<'socket> {
|
|||
/// an argument, it is not captured or consumed, and it never has the value
|
||||
/// `SOLID_NET_INVALID_FD`.
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// This is -2, in two's complement. -1 is `SOLID_NET_INVALID_FD`.
|
||||
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
pub struct OwnedFd {
|
||||
fd: RawFd,
|
||||
fd: ValidRawFd,
|
||||
}
|
||||
|
||||
impl BorrowedFd<'_> {
|
||||
|
@ -108,7 +105,8 @@ impl BorrowedFd<'_> {
|
|||
assert!(fd != -1 as RawFd);
|
||||
// SAFETY: we just asserted that the value is in the valid range and
|
||||
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
|
||||
unsafe { Self { fd, _phantom: PhantomData } }
|
||||
let fd = unsafe { ValidRawFd::new_unchecked(fd) };
|
||||
Self { fd, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -132,21 +130,21 @@ impl BorrowedFd<'_> {
|
|||
impl AsRawFd for BorrowedFd<'_> {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
self.fd.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for OwnedFd {
|
||||
#[inline]
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd
|
||||
self.fd.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for OwnedFd {
|
||||
#[inline]
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
ManuallyDrop::new(self).fd
|
||||
ManuallyDrop::new(self).fd.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -162,14 +160,15 @@ impl FromRawFd for OwnedFd {
|
|||
assert_ne!(fd, -1 as RawFd);
|
||||
// SAFETY: we just asserted that the value is in the valid range and
|
||||
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
|
||||
unsafe { Self { fd } }
|
||||
let fd = unsafe { ValidRawFd::new_unchecked(fd) };
|
||||
Self { fd }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for OwnedFd {
|
||||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe { sys::net::netc::close(self.fd) };
|
||||
unsafe { sys::net::netc::close(self.fd.as_inner()) };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,9 @@ use crate::mem::{self, ManuallyDrop};
|
|||
use crate::sys::cvt;
|
||||
use crate::{fmt, io, sys};
|
||||
|
||||
// The max here is -2, in two's complement. -1 is `INVALID_SOCKET`.
|
||||
type ValidRawSocket = core::num::niche_types::NotAllOnes<RawSocket>;
|
||||
|
||||
/// A borrowed socket.
|
||||
///
|
||||
/// This has a lifetime parameter to tie it to the lifetime of something that
|
||||
|
@ -24,17 +27,10 @@ use crate::{fmt, io, sys};
|
|||
/// socket, which is then borrowed under the same lifetime.
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
|
||||
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
|
||||
#[cfg_attr(
|
||||
target_pointer_width = "64",
|
||||
rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
|
||||
)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||
pub struct BorrowedSocket<'socket> {
|
||||
socket: RawSocket,
|
||||
socket: ValidRawSocket,
|
||||
_phantom: PhantomData<&'socket OwnedSocket>,
|
||||
}
|
||||
|
||||
|
@ -47,17 +43,10 @@ pub struct BorrowedSocket<'socket> {
|
|||
/// argument or returned as an owned value, and it never has the value
|
||||
/// `INVALID_SOCKET`.
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// This is -2, in two's complement. -1 is `INVALID_SOCKET`.
|
||||
#[cfg_attr(target_pointer_width = "32", rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE))]
|
||||
#[cfg_attr(
|
||||
target_pointer_width = "64",
|
||||
rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FF_FF_FF_FF_FE)
|
||||
)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||
pub struct OwnedSocket {
|
||||
socket: RawSocket,
|
||||
socket: ValidRawSocket,
|
||||
}
|
||||
|
||||
impl BorrowedSocket<'_> {
|
||||
|
@ -73,7 +62,8 @@ impl BorrowedSocket<'_> {
|
|||
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||
pub const unsafe fn borrow_raw(socket: RawSocket) -> Self {
|
||||
assert!(socket != sys::c::INVALID_SOCKET as RawSocket);
|
||||
unsafe { Self { socket, _phantom: PhantomData } }
|
||||
let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
|
||||
Self { socket, _phantom: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -172,7 +162,7 @@ fn last_error() -> io::Error {
|
|||
impl AsRawSocket for BorrowedSocket<'_> {
|
||||
#[inline]
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
self.socket
|
||||
self.socket.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +170,7 @@ impl AsRawSocket for BorrowedSocket<'_> {
|
|||
impl AsRawSocket for OwnedSocket {
|
||||
#[inline]
|
||||
fn as_raw_socket(&self) -> RawSocket {
|
||||
self.socket
|
||||
self.socket.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -188,7 +178,7 @@ impl AsRawSocket for OwnedSocket {
|
|||
impl IntoRawSocket for OwnedSocket {
|
||||
#[inline]
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
ManuallyDrop::new(self).socket
|
||||
ManuallyDrop::new(self).socket.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,11 +186,10 @@ impl IntoRawSocket for OwnedSocket {
|
|||
impl FromRawSocket for OwnedSocket {
|
||||
#[inline]
|
||||
unsafe fn from_raw_socket(socket: RawSocket) -> Self {
|
||||
unsafe {
|
||||
debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket);
|
||||
let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
|
||||
Self { socket }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "io_safety", since = "1.63.0")]
|
||||
|
@ -208,7 +197,7 @@ impl Drop for OwnedSocket {
|
|||
#[inline]
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
let _ = sys::c::closesocket(self.socket as sys::c::SOCKET);
|
||||
let _ = sys::c::closesocket(self.socket.as_inner() as sys::c::SOCKET);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,15 +12,12 @@ use crate::sys::unsupported;
|
|||
pub use crate::sys_common::fs::exists;
|
||||
use crate::sys_common::ignore_notfound;
|
||||
|
||||
type CIntNotMinusOne = core::num::niche_types::NotAllOnes<c_int>;
|
||||
|
||||
/// A file descriptor.
|
||||
#[derive(Clone, Copy)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
// libstd/os/raw/mod.rs assures me that every libstd-supported platform has a
|
||||
// 32-bit c_int. Below is -2, in two's complement, but that only works out
|
||||
// because c_int is 32 bits.
|
||||
#[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)]
|
||||
struct FileDesc {
|
||||
fd: c_int,
|
||||
fd: CIntNotMinusOne,
|
||||
}
|
||||
|
||||
impl FileDesc {
|
||||
|
@ -29,12 +26,13 @@ impl FileDesc {
|
|||
assert_ne!(fd, -1i32);
|
||||
// Safety: we just asserted that the value is in the valid range and
|
||||
// isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned)
|
||||
unsafe { FileDesc { fd } }
|
||||
let fd = unsafe { CIntNotMinusOne::new_unchecked(fd) };
|
||||
FileDesc { fd }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn raw(&self) -> c_int {
|
||||
self.fd
|
||||
self.fd.as_inner()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
344
library/std/src/sys/pal/uefi/fs.rs
Normal file
344
library/std/src/sys/pal/uefi/fs.rs
Normal file
|
@ -0,0 +1,344 @@
|
|||
use crate::ffi::OsString;
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
|
||||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::unsupported;
|
||||
|
||||
pub struct File(!);
|
||||
|
||||
pub struct FileAttr(!);
|
||||
|
||||
pub struct ReadDir(!);
|
||||
|
||||
pub struct DirEntry(!);
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct OpenOptions {}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default)]
|
||||
pub struct FileTimes {}
|
||||
|
||||
pub struct FilePermissions(!);
|
||||
|
||||
pub struct FileType(!);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {}
|
||||
|
||||
impl FileAttr {
|
||||
pub fn size(&self) -> u64 {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn perm(&self) -> FilePermissions {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> FileType {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn modified(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn accessed(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn created(&self) -> io::Result<SystemTime> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileAttr {
|
||||
fn clone(&self) -> FileAttr {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FilePermissions {
|
||||
pub fn readonly(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_readonly(&mut self, _readonly: bool) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FilePermissions {
|
||||
fn clone(&self) -> FilePermissions {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for FilePermissions {
|
||||
fn eq(&self, _other: &FilePermissions) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FilePermissions {}
|
||||
|
||||
impl fmt::Debug for FilePermissions {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl FileTimes {
|
||||
pub fn set_accessed(&mut self, _t: SystemTime) {}
|
||||
pub fn set_modified(&mut self, _t: SystemTime) {}
|
||||
}
|
||||
|
||||
impl FileType {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_file(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_symlink(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for FileType {
|
||||
fn clone(&self) -> FileType {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Copy for FileType {}
|
||||
|
||||
impl PartialEq for FileType {
|
||||
fn eq(&self, _other: &FileType) -> bool {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Eq for FileType {}
|
||||
|
||||
impl Hash for FileType {
|
||||
fn hash<H: Hasher>(&self, _h: &mut H) {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for FileType {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for ReadDir {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for ReadDir {
|
||||
type Item = io::Result<DirEntry>;
|
||||
|
||||
fn next(&mut self) -> Option<io::Result<DirEntry>> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DirEntry {
|
||||
pub fn path(&self) -> PathBuf {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_name(&self) -> OsString {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn metadata(&self) -> io::Result<FileAttr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn file_type(&self) -> io::Result<FileType> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenOptions {
|
||||
pub fn new() -> OpenOptions {
|
||||
OpenOptions {}
|
||||
}
|
||||
|
||||
pub fn read(&mut self, _read: bool) {}
|
||||
pub fn write(&mut self, _write: bool) {}
|
||||
pub fn append(&mut self, _append: bool) {}
|
||||
pub fn truncate(&mut self, _truncate: bool) {}
|
||||
pub fn create(&mut self, _create: bool) {}
|
||||
pub fn create_new(&mut self, _create_new: bool) {}
|
||||
}
|
||||
|
||||
impl File {
|
||||
pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn fsync(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn datasync(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn lock(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn lock_shared(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_lock(&self) -> io::Result<bool> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn try_lock_shared(&self) -> io::Result<bool> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn unlock(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn truncate(&self, _size: u64) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_read_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn is_write_vectored(&self) -> bool {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn flush(&self) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn duplicate(&self) -> io::Result<File> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
|
||||
pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl DirBuilder {
|
||||
pub fn new() -> DirBuilder {
|
||||
DirBuilder {}
|
||||
}
|
||||
|
||||
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for File {
|
||||
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn unlink(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
|
||||
match perm.0 {}
|
||||
}
|
||||
|
||||
pub fn rmdir(_p: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn exists(_path: &Path) -> io::Result<bool> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
|
||||
unsupported()
|
||||
}
|
|
@ -15,7 +15,6 @@
|
|||
|
||||
pub mod args;
|
||||
pub mod env;
|
||||
#[path = "../unsupported/fs.rs"]
|
||||
pub mod fs;
|
||||
pub mod helpers;
|
||||
#[path = "../unsupported/io.rs"]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
use core::num::niche_types::Nanoseconds;
|
||||
|
||||
use crate::time::Duration;
|
||||
use crate::{fmt, io};
|
||||
|
||||
|
@ -15,12 +17,6 @@ pub(in crate::sys) const TIMESPEC_MAX_CAPPED: libc::timespec = libc::timespec {
|
|||
tv_nsec: (u64::MAX % NSEC_PER_SEC) as i64,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(0)]
|
||||
#[rustc_layout_scalar_valid_range_end(999_999_999)]
|
||||
struct Nanoseconds(u32);
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct SystemTime {
|
||||
pub(crate) t: Timespec,
|
||||
|
@ -59,14 +55,14 @@ impl fmt::Debug for SystemTime {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("SystemTime")
|
||||
.field("tv_sec", &self.t.tv_sec)
|
||||
.field("tv_nsec", &self.t.tv_nsec.0)
|
||||
.field("tv_nsec", &self.t.tv_nsec)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Timespec {
|
||||
const unsafe fn new_unchecked(tv_sec: i64, tv_nsec: i64) -> Timespec {
|
||||
Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds(tv_nsec as u32) } }
|
||||
Timespec { tv_sec, tv_nsec: unsafe { Nanoseconds::new_unchecked(tv_nsec as u32) } }
|
||||
}
|
||||
|
||||
pub const fn zero() -> Timespec {
|
||||
|
@ -147,12 +143,15 @@ impl Timespec {
|
|||
//
|
||||
// Ideally this code could be rearranged such that it more
|
||||
// directly expresses the lower-cost behavior we want from it.
|
||||
let (secs, nsec) = if self.tv_nsec.0 >= other.tv_nsec.0 {
|
||||
((self.tv_sec - other.tv_sec) as u64, self.tv_nsec.0 - other.tv_nsec.0)
|
||||
let (secs, nsec) = if self.tv_nsec.as_inner() >= other.tv_nsec.as_inner() {
|
||||
(
|
||||
(self.tv_sec - other.tv_sec) as u64,
|
||||
self.tv_nsec.as_inner() - other.tv_nsec.as_inner(),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
(self.tv_sec - other.tv_sec - 1) as u64,
|
||||
self.tv_nsec.0 + (NSEC_PER_SEC as u32) - other.tv_nsec.0,
|
||||
self.tv_nsec.as_inner() + (NSEC_PER_SEC as u32) - other.tv_nsec.as_inner(),
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -170,7 +169,7 @@ impl Timespec {
|
|||
|
||||
// Nano calculations can't overflow because nanos are <1B which fit
|
||||
// in a u32.
|
||||
let mut nsec = other.subsec_nanos() + self.tv_nsec.0;
|
||||
let mut nsec = other.subsec_nanos() + self.tv_nsec.as_inner();
|
||||
if nsec >= NSEC_PER_SEC as u32 {
|
||||
nsec -= NSEC_PER_SEC as u32;
|
||||
secs = secs.checked_add(1)?;
|
||||
|
@ -182,7 +181,7 @@ impl Timespec {
|
|||
let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?;
|
||||
|
||||
// Similar to above, nanos can't overflow.
|
||||
let mut nsec = self.tv_nsec.0 as i32 - other.subsec_nanos() as i32;
|
||||
let mut nsec = self.tv_nsec.as_inner() as i32 - other.subsec_nanos() as i32;
|
||||
if nsec < 0 {
|
||||
nsec += NSEC_PER_SEC as i32;
|
||||
secs = secs.checked_sub(1)?;
|
||||
|
@ -194,7 +193,7 @@ impl Timespec {
|
|||
pub fn to_timespec(&self) -> Option<libc::timespec> {
|
||||
Some(libc::timespec {
|
||||
tv_sec: self.tv_sec.try_into().ok()?,
|
||||
tv_nsec: self.tv_nsec.0.try_into().ok()?,
|
||||
tv_nsec: self.tv_nsec.as_inner().try_into().ok()?,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -203,7 +202,7 @@ impl Timespec {
|
|||
#[cfg(target_os = "nto")]
|
||||
pub(in crate::sys) fn to_timespec_capped(&self) -> Option<libc::timespec> {
|
||||
// Check if timeout in nanoseconds would fit into an u64
|
||||
if (self.tv_nsec.0 as u64)
|
||||
if (self.tv_nsec.as_inner() as u64)
|
||||
.checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?)
|
||||
.is_none()
|
||||
{
|
||||
|
@ -219,7 +218,7 @@ impl Timespec {
|
|||
not(target_arch = "riscv32")
|
||||
))]
|
||||
pub fn to_timespec64(&self) -> __timespec64 {
|
||||
__timespec64::new(self.tv_sec, self.tv_nsec.0 as _)
|
||||
__timespec64::new(self.tv_sec, self.tv_nsec.as_inner() as _)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,7 +292,7 @@ impl fmt::Debug for Instant {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Instant")
|
||||
.field("tv_sec", &self.t.tv_sec)
|
||||
.field("tv_nsec", &self.t.tv_nsec.0)
|
||||
.field("tv_nsec", &self.t.tv_nsec)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -469,7 +469,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
|
|||
// If `compiler-rt` is available ensure that the `c` feature of the
|
||||
// `compiler-builtins` crate is enabled and it's configured to learn where
|
||||
// `compiler-rt` is located.
|
||||
let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins {
|
||||
let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
|
||||
// NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce `submodules = false`, so this is a no-op.
|
||||
// But, the user could still decide to manually use an in-tree submodule.
|
||||
//
|
||||
|
|
|
@ -114,6 +114,9 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
|
|||
} else {
|
||||
println!("fmt: {verb} {len} {adjective}files");
|
||||
}
|
||||
if len > 1000 && !CiEnv::is_ci() {
|
||||
println!("hint: if this number seems too high, try running `git fetch origin master");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {
|
||||
|
|
|
@ -634,6 +634,7 @@ pub struct Target {
|
|||
pub runner: Option<String>,
|
||||
pub no_std: bool,
|
||||
pub codegen_backends: Option<Vec<String>>,
|
||||
pub optimized_compiler_builtins: Option<bool>,
|
||||
}
|
||||
|
||||
impl Target {
|
||||
|
@ -1219,6 +1220,7 @@ define_config! {
|
|||
no_std: Option<bool> = "no-std",
|
||||
codegen_backends: Option<Vec<String>> = "codegen-backends",
|
||||
runner: Option<String> = "runner",
|
||||
optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2096,6 +2098,7 @@ impl Config {
|
|||
target.sanitizers = cfg.sanitizers;
|
||||
target.profiler = cfg.profiler;
|
||||
target.rpath = cfg.rpath;
|
||||
target.optimized_compiler_builtins = cfg.optimized_compiler_builtins;
|
||||
|
||||
if let Some(ref backends) = cfg.codegen_backends {
|
||||
let available_backends = ["llvm", "cranelift", "gcc"];
|
||||
|
@ -2609,6 +2612,13 @@ impl Config {
|
|||
self.target_config.get(&target).and_then(|t| t.rpath).unwrap_or(self.rust_rpath)
|
||||
}
|
||||
|
||||
pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
|
||||
self.target_config
|
||||
.get(&target)
|
||||
.and_then(|t| t.optimized_compiler_builtins)
|
||||
.unwrap_or(self.optimized_compiler_builtins)
|
||||
}
|
||||
|
||||
pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
|
||||
self.codegen_backends(target).contains(&"llvm".to_owned())
|
||||
}
|
||||
|
@ -3162,6 +3172,9 @@ fn check_incompatible_options_for_ci_rustc(
|
|||
|
||||
let profiler = &ci_cfg.profiler;
|
||||
err!(current_cfg.profiler, profiler, "build");
|
||||
|
||||
let optimized_compiler_builtins = &ci_cfg.optimized_compiler_builtins;
|
||||
err!(current_cfg.optimized_compiler_builtins, optimized_compiler_builtins, "build");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -120,6 +120,7 @@ fn override_toml() {
|
|||
"--set=change-id=1".to_owned(),
|
||||
"--set=rust.lto=fat".to_owned(),
|
||||
"--set=rust.deny-warnings=false".to_owned(),
|
||||
"--set=build.optimized-compiler-builtins=true".to_owned(),
|
||||
"--set=build.gdb=\"bar\"".to_owned(),
|
||||
"--set=build.tools=[\"cargo\"]".to_owned(),
|
||||
"--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(),
|
||||
|
@ -127,6 +128,7 @@ fn override_toml() {
|
|||
"--set=target.x86_64-unknown-linux-gnu.rpath=false".to_owned(),
|
||||
"--set=target.aarch64-unknown-linux-gnu.sanitizers=false".to_owned(),
|
||||
"--set=target.aarch64-apple-darwin.runner=apple".to_owned(),
|
||||
"--set=target.aarch64-apple-darwin.optimized-compiler-builtins=false".to_owned(),
|
||||
]),
|
||||
|&_| {
|
||||
toml::from_str(
|
||||
|
@ -167,6 +169,7 @@ runner = "x86_64-runner"
|
|||
);
|
||||
assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
|
||||
assert!(!config.deny_warnings, "setting boolean value");
|
||||
assert!(config.optimized_compiler_builtins, "setting boolean value");
|
||||
assert_eq!(
|
||||
config.tools,
|
||||
Some(["cargo".to_string()].into_iter().collect()),
|
||||
|
@ -193,7 +196,11 @@ runner = "x86_64-runner"
|
|||
..Default::default()
|
||||
};
|
||||
let darwin = TargetSelection::from_user("aarch64-apple-darwin");
|
||||
let darwin_values = Target { runner: Some("apple".into()), ..Default::default() };
|
||||
let darwin_values = Target {
|
||||
runner: Some("apple".into()),
|
||||
optimized_compiler_builtins: Some(false),
|
||||
..Default::default()
|
||||
};
|
||||
assert_eq!(
|
||||
config.target_config,
|
||||
[(x86_64, x86_64_values), (aarch64, aarch64_values), (darwin, darwin_values)]
|
||||
|
|
|
@ -325,4 +325,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
|
|||
severity: ChangeSeverity::Warning,
|
||||
summary: "Removed `rust.parallel-compiler` as it was deprecated in #132282 long time ago.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 135326,
|
||||
severity: ChangeSeverity::Warning,
|
||||
summary: "It is now possible to configure `optimized-compiler-builtins` for per target.",
|
||||
},
|
||||
];
|
||||
|
|
|
@ -181,10 +181,7 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result<
|
|||
/// copy and remove the file otherwise
|
||||
pub fn move_file<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
|
||||
match fs::rename(&from, &to) {
|
||||
// FIXME: Once `ErrorKind::CrossesDevices` is stabilized use
|
||||
// if e.kind() == io::ErrorKind::CrossesDevices {
|
||||
#[cfg(unix)]
|
||||
Err(e) if e.raw_os_error() == Some(libc::EXDEV) => {
|
||||
Err(e) if e.kind() == io::ErrorKind::CrossesDevices => {
|
||||
std::fs::copy(&from, &to)?;
|
||||
std::fs::remove_file(&from)
|
||||
}
|
||||
|
|
|
@ -37,8 +37,11 @@ pub struct Baz {
|
|||
#[no_mangle]
|
||||
pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
|
||||
// CHECK-NOT: loop
|
||||
// CHECK: call
|
||||
// CHECK-SAME: void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
vec.into_iter().map(|e| e as u8).collect()
|
||||
|
@ -48,8 +51,11 @@ pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
|
|||
#[no_mangle]
|
||||
pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> {
|
||||
// CHECK-NOT: loop
|
||||
// CHECK: call
|
||||
// CHECK-SAME: void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
vec.into_iter().map(|e| Wrapper(e)).collect()
|
||||
|
@ -76,8 +82,11 @@ pub fn vec_iterator_cast_signed_nested(vec: Vec<Vec<i32>>) -> Vec<Vec<u32>> {
|
|||
#[no_mangle]
|
||||
pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
|
||||
// CHECK-NOT: loop
|
||||
// CHECK: call
|
||||
// CHECK-SAME: void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
vec.into_iter().map(|e| e.0).collect()
|
||||
|
@ -87,8 +96,11 @@ pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
|
|||
#[no_mangle]
|
||||
pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
|
||||
// CHECK-NOT: loop
|
||||
// CHECK: call
|
||||
// CHECK-SAME: void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect()
|
||||
|
@ -98,8 +110,11 @@ pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
|
|||
#[no_mangle]
|
||||
pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
|
||||
// CHECK-NOT: loop
|
||||
// CHECK: call
|
||||
// CHECK-SAME: void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
|
||||
|
@ -114,8 +129,11 @@ pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
|
|||
#[no_mangle]
|
||||
pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> {
|
||||
// CHECK-NOT: loop
|
||||
// CHECK: call
|
||||
// CHECK-SAME: void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: loop
|
||||
// CHECK-NOT: call
|
||||
|
||||
|
@ -138,6 +156,12 @@ pub fn vec_iterator_cast_unwrap_drop(vec: Vec<Wrapper<String>>) -> Vec<String> {
|
|||
// CHECK-NOT: call
|
||||
// CHECK-NOT: %{{.*}} = mul
|
||||
// CHECK-NOT: %{{.*}} = udiv
|
||||
// CHECK: call
|
||||
// CHECK-SAME: void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
|
||||
// CHECK-NOT: call
|
||||
// CHECK-NOT: %{{.*}} = mul
|
||||
// CHECK-NOT: %{{.*}} = udiv
|
||||
|
||||
vec.into_iter().map(|Wrapper(e)| e).collect()
|
||||
}
|
||||
|
@ -154,6 +178,12 @@ pub fn vec_iterator_cast_wrap_drop(vec: Vec<String>) -> Vec<Wrapper<String>> {
|
|||
// CHECK-NOT: call
|
||||
// CHECK-NOT: %{{.*}} = mul
|
||||
// CHECK-NOT: %{{.*}} = udiv
|
||||
// CHECK: call
|
||||
// CHECK-SAME: void @llvm.assume(i1 %{{.+}})
|
||||
// CHECK-NOT: br i1 %{{.*}}, label %{{.*}}, label %{{.*}}
|
||||
// CHECK-NOT: call
|
||||
// CHECK-NOT: %{{.*}} = mul
|
||||
// CHECK-NOT: %{{.*}} = udiv
|
||||
// CHECK: ret void
|
||||
|
||||
vec.into_iter().map(Wrapper).collect()
|
||||
|
|
|
@ -12,9 +12,6 @@ pub fn noop(v: &mut Vec<u8>) {
|
|||
// CHECK-NOT: call
|
||||
// CHECK: tail call void @llvm.assume
|
||||
// CHECK-NOT: grow_one
|
||||
// llvm-pre-19: call
|
||||
// llvm-pre-19-same: void @llvm.assume
|
||||
// llvm-pre-19-NOT: grow_one
|
||||
// CHECK-NOT: call
|
||||
// CHECK: {{ret|[}]}}
|
||||
if let Some(x) = v.pop() {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// gdb-command:run
|
||||
|
||||
// gdb-command:print plain_string
|
||||
// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {inner: alloc::raw_vec::RawVecInner<alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x[...]}, _marker: core::marker::PhantomData<u8>}, cap: alloc::raw_vec::Cap (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData<u8>}, len: 5}}
|
||||
// gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec<u8, alloc::alloc::Global> {buf: alloc::raw_vec::RawVec<u8, alloc::alloc::Global> {inner: alloc::raw_vec::RawVecInner<alloc::alloc::Global> {ptr: core::ptr::unique::Unique<u8> {pointer: core::ptr::non_null::NonNull<u8> {pointer: 0x[...]}, _marker: core::marker::PhantomData<u8>}, cap: core::num::niche_types::UsizeNoHighBit (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData<u8>}, len: 5}}
|
||||
|
||||
// gdb-command:print plain_str
|
||||
// gdb-check:$2 = "Hello"
|
||||
|
|
|
@ -323,7 +323,7 @@ LL | let _val: (NonZero<u32>, i32) = mem::zeroed();
|
|||
| ^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
||||
|
|
||||
= note: `std::num::NonZero<u32>` must be non-null
|
||||
= note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null
|
||||
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
|
||||
|
||||
error: the type `(NonZero<u32>, i32)` does not permit being left uninitialized
|
||||
--> $DIR/invalid_value.rs:95:41
|
||||
|
@ -332,7 +332,7 @@ LL | let _val: (NonZero<u32>, i32) = mem::uninitialized();
|
|||
| ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
||||
|
|
||||
= note: `std::num::NonZero<u32>` must be non-null
|
||||
= note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null
|
||||
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
|
||||
= note: integers must be initialized
|
||||
|
||||
error: the type `*const dyn Send` does not permit zero-initialization
|
||||
|
@ -415,7 +415,7 @@ note: because `std::num::NonZero<u32>` must be non-null (in this field of the on
|
|||
|
|
||||
LL | Banana(NonZero<u32>),
|
||||
| ^^^^^^^^^^^^
|
||||
= note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null
|
||||
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
|
||||
|
||||
error: the type `OneFruitNonZero` does not permit being left uninitialized
|
||||
--> $DIR/invalid_value.rs:107:37
|
||||
|
@ -429,7 +429,7 @@ note: because `std::num::NonZero<u32>` must be non-null (in this field of the on
|
|||
|
|
||||
LL | Banana(NonZero<u32>),
|
||||
| ^^^^^^^^^^^^
|
||||
= note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null
|
||||
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
|
||||
= note: integers must be initialized
|
||||
|
||||
error: the type `bool` does not permit being left uninitialized
|
||||
|
@ -602,7 +602,7 @@ LL | let _val: NonZero<u32> = mem::transmute(0);
|
|||
| ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
|
||||
|
|
||||
= note: `std::num::NonZero<u32>` must be non-null
|
||||
= note: because `core::num::nonzero::private::NonZeroU32Inner` must be non-null
|
||||
= note: because `core::num::niche_types::NonZeroU32Inner` must be non-null
|
||||
|
||||
error: the type `NonNull<i32>` does not permit zero-initialization
|
||||
--> $DIR/invalid_value.rs:156:34
|
||||
|
|
|
@ -68,7 +68,7 @@ print-type-size type: `Union2<std::num::NonZero<u32>, u32>`: 4 bytes, alignment:
|
|||
print-type-size variant `Union2`: 4 bytes
|
||||
print-type-size field `.a`: 4 bytes
|
||||
print-type-size field `.b`: 4 bytes, offset: 0 bytes, alignment: 4 bytes
|
||||
print-type-size type: `core::num::nonzero::private::NonZeroU32Inner`: 4 bytes, alignment: 4 bytes
|
||||
print-type-size type: `core::num::niche_types::NonZeroU32Inner`: 4 bytes, alignment: 4 bytes
|
||||
print-type-size field `.0`: 4 bytes
|
||||
print-type-size type: `std::num::NonZero<u32>`: 4 bytes, alignment: 4 bytes
|
||||
print-type-size field `.0`: 4 bytes
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue