Rollup merge of #135236 - scottmcm:more-mcp807-library-updates, r=ChrisDenton
Update a bunch of library types for MCP807 This greatly reduces the number of places that actually use the `rustc_layout_scalar_valid_range_*` attributes down to just 3: ``` library/core\src\ptr\non_null.rs 68:#[rustc_layout_scalar_valid_range_start(1)] library/core\src\num\niche_types.rs 19: #[rustc_layout_scalar_valid_range_start($low)] 20: #[rustc_layout_scalar_valid_range_end($high)] ``` Everything else -- PAL Nanoseconds, alloc's `Cap`, niched FDs, etc -- all just wrap those `niche_types` types. r? ghost
This commit is contained in:
commit
351e6188a8
17 changed files with 351 additions and 214 deletions
|
@ -142,6 +142,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
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -357,6 +357,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,10 +186,9 @@ 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);
|
||||
Self { socket }
|
||||
}
|
||||
debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket);
|
||||
let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
|
||||
Self { socket }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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