1
Fork 0

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:
Jacob Pratt 2025-01-11 01:55:05 -05:00 committed by GitHub
commit 351e6188a8
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 351 additions and 214 deletions

View file

@ -142,6 +142,7 @@
#![feature(slice_range)] #![feature(slice_range)]
#![feature(std_internals)] #![feature(std_internals)]
#![feature(str_internals)] #![feature(str_internals)]
#![feature(temporary_niche_types)]
#![feature(trusted_fused)] #![feature(trusted_fused)]
#![feature(trusted_len)] #![feature(trusted_len)]
#![feature(trusted_random_access)] #![feature(trusted_random_access)]

View file

@ -33,21 +33,15 @@ enum AllocInit {
Zeroed, Zeroed,
} }
#[repr(transparent)] type Cap = core::num::niche_types::UsizeNoHighBit;
#[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);
impl Cap { const ZERO_CAP: Cap = unsafe { Cap::new_unchecked(0) };
const ZERO: Cap = unsafe { Cap(0) };
/// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`. /// `Cap(cap)`, except if `T` is a ZST then `Cap::ZERO`.
/// ///
/// # Safety: cap must be <= `isize::MAX`. /// # Safety: cap must be <= `isize::MAX`.
unsafe fn new<T>(cap: usize) -> Self { unsafe fn new_cap<T>(cap: usize) -> Cap {
if T::IS_ZST { Cap::ZERO } else { unsafe { Self(cap) } } if T::IS_ZST { ZERO_CAP } else { unsafe { Cap::new_unchecked(cap) } }
}
} }
/// A low-level utility for more ergonomically allocating, reallocating, and deallocating /// 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 // SAFETY: Precondition passed to the caller
unsafe { unsafe {
let ptr = ptr.cast(); let ptr = ptr.cast();
let capacity = Cap::new::<T>(capacity); let capacity = new_cap::<T>(capacity);
Self { Self {
inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc), inner: RawVecInner::from_raw_parts_in(ptr, capacity, alloc),
_marker: PhantomData, _marker: PhantomData,
@ -275,7 +269,7 @@ impl<T, A: Allocator> RawVec<T, A> {
// SAFETY: Precondition passed to the caller // SAFETY: Precondition passed to the caller
unsafe { unsafe {
let ptr = ptr.cast(); 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 } 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 { const fn new_in(alloc: A, align: usize) -> Self {
let ptr = unsafe { core::mem::transmute(align) }; let ptr = unsafe { core::mem::transmute(align) };
// `cap: 0` means "unallocated". zero-sized types are ignored. // `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))] #[cfg(not(no_global_oom_handling))]
@ -483,7 +477,11 @@ impl<A: Allocator> RawVecInner<A> {
// Allocators currently return a `NonNull<[u8]>` whose length // Allocators currently return a `NonNull<[u8]>` whose length
// matches the size requested. If that ever changes, the capacity // matches the size requested. If that ever changes, the capacity
// here should change to `ptr.len() / mem::size_of::<T>()`. // 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] #[inline]
@ -508,7 +506,7 @@ impl<A: Allocator> RawVecInner<A> {
#[inline] #[inline]
const fn capacity(&self, elem_size: usize) -> usize { 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] #[inline]
@ -518,7 +516,7 @@ impl<A: Allocator> RawVecInner<A> {
#[inline] #[inline]
fn current_memory(&self, elem_layout: Layout) -> Option<(NonNull<u8>, Layout)> { 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 None
} else { } else {
// We could use Layout::array here which ensures the absence of isize and usize overflows // 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 // 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. // support such types. So we can do better by skipping some checks and avoid an unwrap.
unsafe { 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()); let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align());
Some((self.ptr.into(), layout)) Some((self.ptr.into(), layout))
} }
@ -562,7 +560,7 @@ impl<A: Allocator> RawVecInner<A> {
#[inline] #[inline]
#[track_caller] #[track_caller]
fn grow_one(&mut self, elem_layout: Layout) { 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); handle_error(err);
} }
} }
@ -627,7 +625,7 @@ impl<A: Allocator> RawVecInner<A> {
// the size requested. If that ever changes, the capacity here should // the size requested. If that ever changes, the capacity here should
// change to `ptr.len() / mem::size_of::<T>()`. // change to `ptr.len() / mem::size_of::<T>()`.
self.ptr = Unique::from(ptr.cast()); self.ptr = Unique::from(ptr.cast());
self.cap = unsafe { Cap(cap) }; self.cap = unsafe { Cap::new_unchecked(cap) };
} }
fn grow_amortized( fn grow_amortized(
@ -650,7 +648,7 @@ impl<A: Allocator> RawVecInner<A> {
// This guarantees exponential growth. The doubling cannot overflow // This guarantees exponential growth. The doubling cannot overflow
// because `cap <= isize::MAX` and the type of `cap` is `usize`. // 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 cap = cmp::max(min_non_zero_cap(elem_layout.size()), cap);
let new_layout = layout_array(cap, elem_layout)?; let new_layout = layout_array(cap, elem_layout)?;
@ -719,7 +717,7 @@ impl<A: Allocator> RawVecInner<A> {
unsafe { self.alloc.deallocate(ptr, layout) }; unsafe { self.alloc.deallocate(ptr, layout) };
self.ptr = self.ptr =
unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) };
self.cap = Cap::ZERO; self.cap = ZERO_CAP;
} else { } else {
let ptr = unsafe { let ptr = unsafe {
// Layout cannot overflow here because it would have // Layout cannot overflow here because it would have

View file

@ -51,6 +51,10 @@ mod overflow_panic;
mod saturating; mod saturating;
mod wrapping; mod wrapping;
/// 100% perma-unstable
#[doc(hidden)]
pub mod niche_types;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(no_fp_fmt_parse))] #[cfg(not(no_fp_fmt_parse))]
pub use dec2flt::ParseFloatError; pub use dec2flt::ParseFloatError;

View 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;
}

View file

@ -37,41 +37,12 @@ pub unsafe trait ZeroablePrimitive: Sized + Copy + private::Sealed {
macro_rules! impl_zeroable_primitive { macro_rules! impl_zeroable_primitive {
($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => { ($($NonZeroInner:ident ( $primitive:ty )),+ $(,)?) => {
mod private { mod private {
use super::*;
#[unstable( #[unstable(
feature = "nonzero_internals", feature = "nonzero_internals",
reason = "implementation detail which may disappear or be replaced at any time", reason = "implementation detail which may disappear or be replaced at any time",
issue = "none" issue = "none"
)] )]
pub trait Sealed {} 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" issue = "none"
)] )]
unsafe impl ZeroablePrimitive for $primitive { unsafe impl ZeroablePrimitive for $primitive {
type NonZeroInner = private::$NonZeroInner; type NonZeroInner = super::niche_types::$NonZeroInner;
} }
)+ )+
}; };

View file

@ -21,6 +21,7 @@
use crate::fmt; use crate::fmt;
use crate::iter::Sum; use crate::iter::Sum;
use crate::num::niche_types::Nanoseconds;
use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign}; use crate::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};
const NANOS_PER_SEC: u32 = 1_000_000_000; 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")] #[unstable(feature = "duration_units", issue = "120301")]
const DAYS_PER_WEEK: u64 = 7; 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 /// A `Duration` type to represent a span of time, typically used for system
/// timeouts. /// timeouts.
/// ///
@ -211,14 +194,14 @@ impl Duration {
pub const fn new(secs: u64, nanos: u32) -> Duration { pub const fn new(secs: u64, nanos: u32) -> Duration {
if nanos < NANOS_PER_SEC { if nanos < NANOS_PER_SEC {
// SAFETY: nanos < NANOS_PER_SEC, therefore nanos is within the valid range // 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 { } else {
let secs = secs let secs = secs
.checked_add((nanos / NANOS_PER_SEC) as u64) .checked_add((nanos / NANOS_PER_SEC) as u64)
.expect("overflow in Duration::new"); .expect("overflow in Duration::new");
let nanos = nanos % NANOS_PER_SEC; let nanos = nanos % NANOS_PER_SEC;
// SAFETY: nanos % NANOS_PER_SEC < NANOS_PER_SEC, therefore nanos is within the valid range // 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; let subsec_millis = (millis % MILLIS_PER_SEC) as u32;
// SAFETY: (x % 1_000) * 1_000_000 < 1_000_000_000 // SAFETY: (x % 1_000) * 1_000_000 < 1_000_000_000
// => x % 1_000 < 1_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 } Duration { secs, nanos: subsec_nanos }
} }
@ -289,7 +272,7 @@ impl Duration {
let subsec_micros = (micros % MICROS_PER_SEC) as u32; let subsec_micros = (micros % MICROS_PER_SEC) as u32;
// SAFETY: (x % 1_000_000) * 1_000 < 1_000_000_000 // SAFETY: (x % 1_000_000) * 1_000 < 1_000_000_000
// => x % 1_000_000 < 1_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 } Duration { secs, nanos: subsec_nanos }
} }
@ -320,7 +303,7 @@ impl Duration {
let secs = nanos / NANOS_PER_SEC; let secs = nanos / NANOS_PER_SEC;
let subsec_nanos = (nanos % NANOS_PER_SEC) as u32; let subsec_nanos = (nanos % NANOS_PER_SEC) as u32;
// SAFETY: x % 1_000_000_000 < 1_000_000_000 // 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 } Duration { secs, nanos: subsec_nanos }
} }
@ -458,7 +441,7 @@ impl Duration {
#[rustc_const_stable(feature = "duration_zero", since = "1.53.0")] #[rustc_const_stable(feature = "duration_zero", since = "1.53.0")]
#[inline] #[inline]
pub const fn is_zero(&self) -> bool { 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`. /// Returns the number of _whole_ seconds contained by this `Duration`.
@ -509,7 +492,7 @@ impl Duration {
#[must_use] #[must_use]
#[inline] #[inline]
pub const fn subsec_millis(&self) -> u32 { 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. /// Returns the fractional part of this `Duration`, in whole microseconds.
@ -532,7 +515,7 @@ impl Duration {
#[must_use] #[must_use]
#[inline] #[inline]
pub const fn subsec_micros(&self) -> u32 { 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. /// Returns the fractional part of this `Duration`, in nanoseconds.
@ -555,7 +538,7 @@ impl Duration {
#[must_use] #[must_use]
#[inline] #[inline]
pub const fn subsec_nanos(&self) -> u32 { 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`. /// Returns the total number of whole milliseconds contained by this `Duration`.
@ -573,7 +556,8 @@ impl Duration {
#[must_use] #[must_use]
#[inline] #[inline]
pub const fn as_millis(&self) -> u128 { 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`. /// Returns the total number of whole microseconds contained by this `Duration`.
@ -591,7 +575,8 @@ impl Duration {
#[must_use] #[must_use]
#[inline] #[inline]
pub const fn as_micros(&self) -> u128 { 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`. /// Returns the total number of nanoseconds contained by this `Duration`.
@ -609,7 +594,7 @@ impl Duration {
#[must_use] #[must_use]
#[inline] #[inline]
pub const fn as_nanos(&self) -> u128 { 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`. /// 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")] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
pub const fn checked_add(self, rhs: Duration) -> Option<Duration> { pub const fn checked_add(self, rhs: Duration) -> Option<Duration> {
if let Some(mut secs) = self.secs.checked_add(rhs.secs) { 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 { if nanos >= NANOS_PER_SEC {
nanos -= NANOS_PER_SEC; nanos -= NANOS_PER_SEC;
if let Some(new_secs) = secs.checked_add(1) { 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")] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> { pub const fn checked_sub(self, rhs: Duration) -> Option<Duration> {
if let Some(mut secs) = self.secs.checked_sub(rhs.secs) { if let Some(mut secs) = self.secs.checked_sub(rhs.secs) {
let nanos = if self.nanos.0 >= rhs.nanos.0 { let nanos = if self.nanos.as_inner() >= rhs.nanos.as_inner() {
self.nanos.0 - rhs.nanos.0 self.nanos.as_inner() - rhs.nanos.as_inner()
} else if let Some(sub_secs) = secs.checked_sub(1) { } else if let Some(sub_secs) = secs.checked_sub(1) {
secs = sub_secs; secs = sub_secs;
self.nanos.0 + NANOS_PER_SEC - rhs.nanos.0 self.nanos.as_inner() + NANOS_PER_SEC - rhs.nanos.as_inner()
} else { } else {
return None; return None;
}; };
@ -763,7 +748,7 @@ impl Duration {
#[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")] #[rustc_const_stable(feature = "duration_consts_2", since = "1.58.0")]
pub const fn checked_mul(self, rhs: u32) -> Option<Duration> { pub const fn checked_mul(self, rhs: u32) -> Option<Duration> {
// Multiply nanoseconds as u64, because it cannot overflow that way. // 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 extra_secs = total_nanos / (NANOS_PER_SEC as u64);
let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32; let nanos = (total_nanos % (NANOS_PER_SEC as u64)) as u32;
// FIXME(const-hack): use `and_then` once that is possible. // 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> { pub const fn checked_div(self, rhs: u32) -> Option<Duration> {
if rhs != 0 { if rhs != 0 {
let (secs, extra_secs) = (self.secs / (rhs as u64), self.secs % (rhs as u64)); 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 += nanos +=
((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32; ((extra_secs * (NANOS_PER_SEC as u64) + extra_nanos as u64) / (rhs as u64)) as u32;
debug_assert!(nanos < NANOS_PER_SEC); debug_assert!(nanos < NANOS_PER_SEC);
@ -846,7 +832,7 @@ impl Duration {
#[inline] #[inline]
#[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")]
pub const fn as_secs_f64(&self) -> f64 { 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`. /// Returns the number of seconds contained by this `Duration` as `f32`.
@ -865,7 +851,7 @@ impl Duration {
#[inline] #[inline]
#[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")]
pub const fn as_secs_f32(&self) -> f32 { 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`. /// Returns the number of milliseconds contained by this `Duration` as `f64`.
@ -885,7 +871,7 @@ impl Duration {
#[inline] #[inline]
pub const fn as_millis_f64(&self) -> f64 { pub const fn as_millis_f64(&self) -> f64 {
(self.secs as f64) * (MILLIS_PER_SEC as 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`. /// Returns the number of milliseconds contained by this `Duration` as `f32`.
@ -905,7 +891,7 @@ impl Duration {
#[inline] #[inline]
pub const fn as_millis_f32(&self) -> f32 { pub const fn as_millis_f32(&self) -> f32 {
(self.secs as f32) * (MILLIS_PER_SEC as 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 /// Creates a new `Duration` from the specified number of seconds represented
@ -1084,8 +1070,9 @@ impl Duration {
#[inline] #[inline]
#[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")]
pub const fn div_duration_f64(self, rhs: Duration) -> f64 { 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 self_nanos =
let rhs_nanos = (rhs.secs as f64) * (NANOS_PER_SEC as f64) + (rhs.nanos.0 as f64); (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 self_nanos / rhs_nanos
} }
@ -1105,8 +1092,9 @@ impl Duration {
#[inline] #[inline]
#[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")] #[rustc_const_stable(feature = "duration_consts_float", since = "1.83.0")]
pub const fn div_duration_f32(self, rhs: Duration) -> f32 { 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 self_nanos =
let rhs_nanos = (rhs.secs as f32) * (NANOS_PER_SEC as f32) + (rhs.nanos.0 as f32); (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 self_nanos / rhs_nanos
} }
} }
@ -1201,13 +1189,13 @@ macro_rules! sum_durations {
for entry in $iter { for entry in $iter {
total_secs = total_secs =
total_secs.checked_add(entry.secs).expect("overflow in iter::sum over durations"); 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, Some(n) => n,
None => { None => {
total_secs = total_secs total_secs = total_secs
.checked_add(total_nanos / NANOS_PER_SEC as u64) .checked_add(total_nanos / NANOS_PER_SEC as u64)
.expect("overflow in iter::sum over durations"); .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 { "" }; let prefix = if f.sign_plus() { "+" } else { "" };
if self.secs > 0 { if self.secs > 0 {
fmt_decimal(f, self.secs, self.nanos.0, NANOS_PER_SEC / 10, prefix, "s") fmt_decimal(f, self.secs, self.nanos.as_inner(), NANOS_PER_SEC / 10, prefix, "s")
} else if self.nanos.0 >= NANOS_PER_MILLI { } else if self.nanos.as_inner() >= NANOS_PER_MILLI {
fmt_decimal( fmt_decimal(
f, f,
(self.nanos.0 / NANOS_PER_MILLI) as u64, (self.nanos.as_inner() / NANOS_PER_MILLI) as u64,
self.nanos.0 % NANOS_PER_MILLI, self.nanos.as_inner() % NANOS_PER_MILLI,
NANOS_PER_MILLI / 10, NANOS_PER_MILLI / 10,
prefix, prefix,
"ms", "ms",
) )
} else if self.nanos.0 >= NANOS_PER_MICRO { } else if self.nanos.as_inner() >= NANOS_PER_MICRO {
fmt_decimal( fmt_decimal(
f, f,
(self.nanos.0 / NANOS_PER_MICRO) as u64, (self.nanos.as_inner() / NANOS_PER_MICRO) as u64,
self.nanos.0 % NANOS_PER_MICRO, self.nanos.as_inner() % NANOS_PER_MICRO,
NANOS_PER_MICRO / 10, NANOS_PER_MICRO / 10,
prefix, prefix,
"µs", "µs",
) )
} else { } 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")
} }
} }
} }

View file

@ -357,6 +357,7 @@
#![feature(str_internals)] #![feature(str_internals)]
#![feature(strict_provenance_atomic_ptr)] #![feature(strict_provenance_atomic_ptr)]
#![feature(sync_unsafe_cell)] #![feature(sync_unsafe_cell)]
#![feature(temporary_niche_types)]
#![feature(ub_checks)] #![feature(ub_checks)]
#![feature(used_with_arg)] #![feature(used_with_arg)]
// tidy-alphabetical-end // tidy-alphabetical-end

View file

@ -11,6 +11,8 @@ use crate::sys::cvt;
use crate::sys_common::{AsInner, FromInner, IntoInner}; use crate::sys_common::{AsInner, FromInner, IntoInner};
use crate::{fmt, fs, io}; use crate::{fmt, fs, io};
type ValidRawFd = core::num::niche_types::NotAllOnes<RawFd>;
/// A borrowed file descriptor. /// A borrowed file descriptor.
/// ///
/// This has a lifetime parameter to tie it to the lifetime of something that owns the file /// 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. /// instead, but this is not supported on all platforms.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(transparent)] #[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] #[rustc_nonnull_optimization_guaranteed]
#[stable(feature = "io_safety", since = "1.63.0")] #[stable(feature = "io_safety", since = "1.63.0")]
pub struct BorrowedFd<'fd> { pub struct BorrowedFd<'fd> {
fd: RawFd, fd: ValidRawFd,
_phantom: PhantomData<&'fd OwnedFd>, _phantom: PhantomData<&'fd OwnedFd>,
} }
@ -56,15 +53,10 @@ pub struct BorrowedFd<'fd> {
/// ///
/// You can use [`AsFd::as_fd`] to obtain a [`BorrowedFd`]. /// You can use [`AsFd::as_fd`] to obtain a [`BorrowedFd`].
#[repr(transparent)] #[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] #[rustc_nonnull_optimization_guaranteed]
#[stable(feature = "io_safety", since = "1.63.0")] #[stable(feature = "io_safety", since = "1.63.0")]
pub struct OwnedFd { pub struct OwnedFd {
fd: RawFd, fd: ValidRawFd,
} }
impl BorrowedFd<'_> { impl BorrowedFd<'_> {
@ -80,7 +72,8 @@ impl BorrowedFd<'_> {
pub const unsafe fn borrow_raw(fd: RawFd) -> Self { pub const unsafe fn borrow_raw(fd: RawFd) -> Self {
assert!(fd != u32::MAX as RawFd); 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) // 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<'_> { impl AsRawFd for BorrowedFd<'_> {
#[inline] #[inline]
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
self.fd self.fd.as_inner()
} }
} }
@ -138,7 +131,7 @@ impl AsRawFd for BorrowedFd<'_> {
impl AsRawFd for OwnedFd { impl AsRawFd for OwnedFd {
#[inline] #[inline]
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
self.fd self.fd.as_inner()
} }
} }
@ -146,7 +139,7 @@ impl AsRawFd for OwnedFd {
impl IntoRawFd for OwnedFd { impl IntoRawFd for OwnedFd {
#[inline] #[inline]
fn into_raw_fd(self) -> RawFd { 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 { unsafe fn from_raw_fd(fd: RawFd) -> Self {
assert_ne!(fd, u32::MAX as RawFd); 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) // 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(not(target_os = "hermit"))]
{ {
#[cfg(unix)] #[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")] #[cfg(target_os = "hermit")]
let _ = hermit_abi::close(self.fd); let _ = hermit_abi::close(self.fd.as_inner());
} }
} }
} }

View file

@ -54,6 +54,9 @@ use crate::{fmt, net, sys};
/// Raw file descriptors. /// Raw file descriptors.
pub type RawFd = i32; 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. /// A borrowed SOLID Sockets file descriptor.
/// ///
/// This has a lifetime parameter to tie it to the lifetime of something that /// 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. /// socket, which is then borrowed under the same lifetime.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(transparent)] #[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] #[rustc_nonnull_optimization_guaranteed]
pub struct BorrowedFd<'socket> { pub struct BorrowedFd<'socket> {
fd: RawFd, fd: ValidRawFd,
_phantom: PhantomData<&'socket OwnedFd>, _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 /// an argument, it is not captured or consumed, and it never has the value
/// `SOLID_NET_INVALID_FD`. /// `SOLID_NET_INVALID_FD`.
#[repr(transparent)] #[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] #[rustc_nonnull_optimization_guaranteed]
pub struct OwnedFd { pub struct OwnedFd {
fd: RawFd, fd: ValidRawFd,
} }
impl BorrowedFd<'_> { impl BorrowedFd<'_> {
@ -108,7 +105,8 @@ impl BorrowedFd<'_> {
assert!(fd != -1 as RawFd); assert!(fd != -1 as RawFd);
// SAFETY: we just asserted that the value is in the valid range and // 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) // 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<'_> { impl AsRawFd for BorrowedFd<'_> {
#[inline] #[inline]
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
self.fd self.fd.as_inner()
} }
} }
impl AsRawFd for OwnedFd { impl AsRawFd for OwnedFd {
#[inline] #[inline]
fn as_raw_fd(&self) -> RawFd { fn as_raw_fd(&self) -> RawFd {
self.fd self.fd.as_inner()
} }
} }
impl IntoRawFd for OwnedFd { impl IntoRawFd for OwnedFd {
#[inline] #[inline]
fn into_raw_fd(self) -> RawFd { 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); assert_ne!(fd, -1 as RawFd);
// SAFETY: we just asserted that the value is in the valid range and // 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) // 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 { impl Drop for OwnedFd {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
unsafe { sys::net::netc::close(self.fd) }; unsafe { sys::net::netc::close(self.fd.as_inner()) };
} }
} }

View file

@ -9,6 +9,9 @@ use crate::mem::{self, ManuallyDrop};
use crate::sys::cvt; use crate::sys::cvt;
use crate::{fmt, io, sys}; 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. /// A borrowed socket.
/// ///
/// This has a lifetime parameter to tie it to the lifetime of something that /// 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. /// socket, which is then borrowed under the same lifetime.
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
#[repr(transparent)] #[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] #[rustc_nonnull_optimization_guaranteed]
#[stable(feature = "io_safety", since = "1.63.0")] #[stable(feature = "io_safety", since = "1.63.0")]
pub struct BorrowedSocket<'socket> { pub struct BorrowedSocket<'socket> {
socket: RawSocket, socket: ValidRawSocket,
_phantom: PhantomData<&'socket OwnedSocket>, _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 /// argument or returned as an owned value, and it never has the value
/// `INVALID_SOCKET`. /// `INVALID_SOCKET`.
#[repr(transparent)] #[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] #[rustc_nonnull_optimization_guaranteed]
#[stable(feature = "io_safety", since = "1.63.0")] #[stable(feature = "io_safety", since = "1.63.0")]
pub struct OwnedSocket { pub struct OwnedSocket {
socket: RawSocket, socket: ValidRawSocket,
} }
impl BorrowedSocket<'_> { impl BorrowedSocket<'_> {
@ -73,7 +62,8 @@ impl BorrowedSocket<'_> {
#[stable(feature = "io_safety", since = "1.63.0")] #[stable(feature = "io_safety", since = "1.63.0")]
pub const unsafe fn borrow_raw(socket: RawSocket) -> Self { pub const unsafe fn borrow_raw(socket: RawSocket) -> Self {
assert!(socket != sys::c::INVALID_SOCKET as RawSocket); 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<'_> { impl AsRawSocket for BorrowedSocket<'_> {
#[inline] #[inline]
fn as_raw_socket(&self) -> RawSocket { fn as_raw_socket(&self) -> RawSocket {
self.socket self.socket.as_inner()
} }
} }
@ -180,7 +170,7 @@ impl AsRawSocket for BorrowedSocket<'_> {
impl AsRawSocket for OwnedSocket { impl AsRawSocket for OwnedSocket {
#[inline] #[inline]
fn as_raw_socket(&self) -> RawSocket { fn as_raw_socket(&self) -> RawSocket {
self.socket self.socket.as_inner()
} }
} }
@ -188,7 +178,7 @@ impl AsRawSocket for OwnedSocket {
impl IntoRawSocket for OwnedSocket { impl IntoRawSocket for OwnedSocket {
#[inline] #[inline]
fn into_raw_socket(self) -> RawSocket { 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 { impl FromRawSocket for OwnedSocket {
#[inline] #[inline]
unsafe fn from_raw_socket(socket: RawSocket) -> Self { unsafe fn from_raw_socket(socket: RawSocket) -> Self {
unsafe {
debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket); debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket);
let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
Self { socket } Self { socket }
} }
}
} }
#[stable(feature = "io_safety", since = "1.63.0")] #[stable(feature = "io_safety", since = "1.63.0")]
@ -208,7 +197,7 @@ impl Drop for OwnedSocket {
#[inline] #[inline]
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
let _ = sys::c::closesocket(self.socket as sys::c::SOCKET); let _ = sys::c::closesocket(self.socket.as_inner() as sys::c::SOCKET);
} }
} }
} }

View file

@ -12,15 +12,12 @@ use crate::sys::unsupported;
pub use crate::sys_common::fs::exists; pub use crate::sys_common::fs::exists;
use crate::sys_common::ignore_notfound; use crate::sys_common::ignore_notfound;
type CIntNotMinusOne = core::num::niche_types::NotAllOnes<c_int>;
/// A file descriptor. /// A file descriptor.
#[derive(Clone, Copy)] #[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 { struct FileDesc {
fd: c_int, fd: CIntNotMinusOne,
} }
impl FileDesc { impl FileDesc {
@ -29,12 +26,13 @@ impl FileDesc {
assert_ne!(fd, -1i32); assert_ne!(fd, -1i32);
// Safety: we just asserted that the value is in the valid range and // 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) // 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] #[inline]
fn raw(&self) -> c_int { fn raw(&self) -> c_int {
self.fd self.fd.as_inner()
} }
} }

View file

@ -1,3 +1,5 @@
use core::num::niche_types::Nanoseconds;
use crate::time::Duration; use crate::time::Duration;
use crate::{fmt, io}; 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, 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)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SystemTime { pub struct SystemTime {
pub(crate) t: Timespec, pub(crate) t: Timespec,
@ -59,14 +55,14 @@ impl fmt::Debug for SystemTime {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("SystemTime") f.debug_struct("SystemTime")
.field("tv_sec", &self.t.tv_sec) .field("tv_sec", &self.t.tv_sec)
.field("tv_nsec", &self.t.tv_nsec.0) .field("tv_nsec", &self.t.tv_nsec)
.finish() .finish()
} }
} }
impl Timespec { impl Timespec {
const unsafe fn new_unchecked(tv_sec: i64, tv_nsec: i64) -> 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 { pub const fn zero() -> Timespec {
@ -147,12 +143,15 @@ impl Timespec {
// //
// Ideally this code could be rearranged such that it more // Ideally this code could be rearranged such that it more
// directly expresses the lower-cost behavior we want from it. // directly expresses the lower-cost behavior we want from it.
let (secs, nsec) = if 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.0 - other.tv_nsec.0) (
(self.tv_sec - other.tv_sec) as u64,
self.tv_nsec.as_inner() - other.tv_nsec.as_inner(),
)
} else { } else {
( (
(self.tv_sec - other.tv_sec - 1) as u64, (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 // Nano calculations can't overflow because nanos are <1B which fit
// in a u32. // 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 { if nsec >= NSEC_PER_SEC as u32 {
nsec -= NSEC_PER_SEC as u32; nsec -= NSEC_PER_SEC as u32;
secs = secs.checked_add(1)?; secs = secs.checked_add(1)?;
@ -182,7 +181,7 @@ impl Timespec {
let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?; let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?;
// Similar to above, nanos can't overflow. // 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 { if nsec < 0 {
nsec += NSEC_PER_SEC as i32; nsec += NSEC_PER_SEC as i32;
secs = secs.checked_sub(1)?; secs = secs.checked_sub(1)?;
@ -194,7 +193,7 @@ impl Timespec {
pub fn to_timespec(&self) -> Option<libc::timespec> { pub fn to_timespec(&self) -> Option<libc::timespec> {
Some(libc::timespec { Some(libc::timespec {
tv_sec: self.tv_sec.try_into().ok()?, 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")] #[cfg(target_os = "nto")]
pub(in crate::sys) fn to_timespec_capped(&self) -> Option<libc::timespec> { pub(in crate::sys) fn to_timespec_capped(&self) -> Option<libc::timespec> {
// Check if timeout in nanoseconds would fit into an u64 // 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)?) .checked_add((self.tv_sec as u64).checked_mul(NSEC_PER_SEC)?)
.is_none() .is_none()
{ {
@ -219,7 +218,7 @@ impl Timespec {
not(target_arch = "riscv32") not(target_arch = "riscv32")
))] ))]
pub fn to_timespec64(&self) -> __timespec64 { 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 { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Instant") f.debug_struct("Instant")
.field("tv_sec", &self.t.tv_sec) .field("tv_sec", &self.t.tv_sec)
.field("tv_nsec", &self.t.tv_nsec.0) .field("tv_nsec", &self.t.tv_nsec)
.finish() .finish()
} }
} }

View file

@ -37,8 +37,11 @@ pub struct Baz {
#[no_mangle] #[no_mangle]
pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> { pub fn vec_iterator_cast_primitive(vec: Vec<i8>) -> Vec<u8> {
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK: call // CHECK-NOT: call
// CHECK-SAME: void @llvm.assume(i1 %{{.+}}) // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop
// CHECK-NOT: call
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK-NOT: call // CHECK-NOT: call
vec.into_iter().map(|e| e as u8).collect() 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] #[no_mangle]
pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> { pub fn vec_iterator_cast_wrapper(vec: Vec<u8>) -> Vec<Wrapper<u8>> {
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK: call // CHECK-NOT: call
// CHECK-SAME: void @llvm.assume(i1 %{{.+}}) // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop
// CHECK-NOT: call
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK-NOT: call // CHECK-NOT: call
vec.into_iter().map(|e| Wrapper(e)).collect() 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] #[no_mangle]
pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> { pub fn vec_iterator_cast_unwrap(vec: Vec<Wrapper<u8>>) -> Vec<u8> {
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK: call // CHECK-NOT: call
// CHECK-SAME: void @llvm.assume(i1 %{{.+}}) // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop
// CHECK-NOT: call
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK-NOT: call // CHECK-NOT: call
vec.into_iter().map(|e| e.0).collect() 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] #[no_mangle]
pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> { pub fn vec_iterator_cast_aggregate(vec: Vec<[u64; 4]>) -> Vec<Foo> {
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK: call // CHECK-NOT: call
// CHECK-SAME: void @llvm.assume(i1 %{{.+}}) // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop
// CHECK-NOT: call
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK-NOT: call // CHECK-NOT: call
vec.into_iter().map(|e| unsafe { std::mem::transmute(e) }).collect() 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] #[no_mangle]
pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> { pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK: call // CHECK-NOT: call
// CHECK-SAME: void @llvm.assume(i1 %{{.+}}) // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop
// CHECK-NOT: call
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK-NOT: call // CHECK-NOT: call
@ -114,8 +129,11 @@ pub fn vec_iterator_cast_deaggregate_tra(vec: Vec<Bar>) -> Vec<[u64; 4]> {
#[no_mangle] #[no_mangle]
pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> { pub fn vec_iterator_cast_deaggregate_fold(vec: Vec<Baz>) -> Vec<[u64; 4]> {
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK: call // CHECK-NOT: call
// CHECK-SAME: void @llvm.assume(i1 %{{.+}}) // CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop
// CHECK-NOT: call
// CHECK: call{{.+}}void @llvm.assume(i1 %{{.+}})
// CHECK-NOT: loop // CHECK-NOT: loop
// CHECK-NOT: call // 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: call
// CHECK-NOT: %{{.*}} = mul // CHECK-NOT: %{{.*}} = mul
// CHECK-NOT: %{{.*}} = udiv // 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() 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: call
// CHECK-NOT: %{{.*}} = mul // CHECK-NOT: %{{.*}} = mul
// CHECK-NOT: %{{.*}} = udiv // 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 // CHECK: ret void
vec.into_iter().map(Wrapper).collect() vec.into_iter().map(Wrapper).collect()

View file

@ -12,9 +12,6 @@ pub fn noop(v: &mut Vec<u8>) {
// CHECK-NOT: call // CHECK-NOT: call
// CHECK: tail call void @llvm.assume // CHECK: tail call void @llvm.assume
// CHECK-NOT: grow_one // 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-NOT: call
// CHECK: {{ret|[}]}} // CHECK: {{ret|[}]}}
if let Some(x) = v.pop() { if let Some(x) = v.pop() {

View file

@ -7,7 +7,7 @@
// gdb-command:run // gdb-command:run
// gdb-command:print plain_string // 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-command:print plain_str
// gdb-check:$2 = "Hello" // gdb-check:$2 = "Hello"

View file

@ -323,7 +323,7 @@ LL | let _val: (NonZero<u32>, i32) = mem::zeroed();
| ^^^^^^^^^^^^^ this code causes undefined behavior when executed | ^^^^^^^^^^^^^ this code causes undefined behavior when executed
| |
= note: `std::num::NonZero<u32>` must be non-null = 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 error: the type `(NonZero<u32>, i32)` does not permit being left uninitialized
--> $DIR/invalid_value.rs:95:41 --> $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 | ^^^^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
| |
= note: `std::num::NonZero<u32>` must be non-null = 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 = note: integers must be initialized
error: the type `*const dyn Send` does not permit zero-initialization 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>), 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 error: the type `OneFruitNonZero` does not permit being left uninitialized
--> $DIR/invalid_value.rs:107:37 --> $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>), 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 = note: integers must be initialized
error: the type `bool` does not permit being left uninitialized 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 | ^^^^^^^^^^^^^^^^^ this code causes undefined behavior when executed
| |
= note: `std::num::NonZero<u32>` must be non-null = 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 error: the type `NonNull<i32>` does not permit zero-initialization
--> $DIR/invalid_value.rs:156:34 --> $DIR/invalid_value.rs:156:34

View file

@ -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 variant `Union2`: 4 bytes
print-type-size field `.a`: 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 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 field `.0`: 4 bytes
print-type-size type: `std::num::NonZero<u32>`: 4 bytes, alignment: 4 bytes print-type-size type: `std::num::NonZero<u32>`: 4 bytes, alignment: 4 bytes
print-type-size field `.0`: 4 bytes print-type-size field `.0`: 4 bytes