1
Fork 0

Auto merge of #135357 - jhpratt:rollup-gs00yt3, r=jhpratt

Rollup of 6 pull requests

Successful merges:

 - #134074 (bootstrap: `std::io::ErrorKind::CrossesDevices` is finally stable)
 - #135236 (Update a bunch of library types for MCP807)
 - #135301 (re-add a warning for old master branch, but with much simpler logic)
 - #135324 (Initial fs module for uefi)
 - #135326 (support target specific `optimized-compiler-builtins`)
 - #135347 (Use `NonNull::without_provenance` within the standard library)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-01-11 09:17:06 +00:00
commit ce55b2052d
30 changed files with 748 additions and 250 deletions

View file

@ -922,6 +922,15 @@
# argument as the test binary.
#runner = <none> (string)
# Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics
# on this target.
# Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt`
# sources are available.
#
# Setting this to `false` generates slower code, but removes the requirement for a C toolchain in
# order to run `x check`.
#optimized-compiler-builtins = build.optimized-compiler-builtins (bool)
# =============================================================================
# Distribution options
#

View file

@ -126,6 +126,7 @@
#![feature(local_waker)]
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_uninit_array_transpose)]
#![feature(nonnull_provenance)]
#![feature(panic_internals)]
#![feature(pattern)]
#![feature(pin_coerce_unsized_trait)]
@ -142,6 +143,7 @@
#![feature(slice_range)]
#![feature(std_internals)]
#![feature(str_internals)]
#![feature(temporary_niche_types)]
#![feature(trusted_fused)]
#![feature(trusted_len)]
#![feature(trusted_random_access)]

View file

@ -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) } }
}
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

View file

@ -252,6 +252,7 @@ use core::intrinsics::abort;
use core::iter;
use core::marker::{PhantomData, Unsize};
use core::mem::{self, ManuallyDrop, align_of_val_raw};
use core::num::NonZeroUsize;
use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, LegacyReceiver};
use core::panic::{RefUnwindSafe, UnwindSafe};
#[cfg(not(no_global_oom_handling))]
@ -3027,12 +3028,7 @@ impl<T> Weak<T> {
#[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")]
#[must_use]
pub const fn new() -> Weak<T> {
Weak {
ptr: unsafe {
NonNull::new_unchecked(ptr::without_provenance_mut::<RcInner<T>>(usize::MAX))
},
alloc: Global,
}
Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc: Global }
}
}
@ -3054,12 +3050,7 @@ impl<T, A: Allocator> Weak<T, A> {
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn new_in(alloc: A) -> Weak<T, A> {
Weak {
ptr: unsafe {
NonNull::new_unchecked(ptr::without_provenance_mut::<RcInner<T>>(usize::MAX))
},
alloc,
}
Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc }
}
}

View file

@ -18,6 +18,7 @@ use core::intrinsics::abort;
use core::iter;
use core::marker::{PhantomData, Unsize};
use core::mem::{self, ManuallyDrop, align_of_val_raw};
use core::num::NonZeroUsize;
use core::ops::{CoerceUnsized, Deref, DerefPure, DispatchFromDyn, LegacyReceiver};
use core::panic::{RefUnwindSafe, UnwindSafe};
use core::pin::{Pin, PinCoerceUnsized};
@ -2687,12 +2688,7 @@ impl<T> Weak<T> {
#[rustc_const_stable(feature = "const_weak_new", since = "1.73.0")]
#[must_use]
pub const fn new() -> Weak<T> {
Weak {
ptr: unsafe {
NonNull::new_unchecked(ptr::without_provenance_mut::<ArcInner<T>>(usize::MAX))
},
alloc: Global,
}
Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc: Global }
}
}
@ -2717,12 +2713,7 @@ impl<T, A: Allocator> Weak<T, A> {
#[inline]
#[unstable(feature = "allocator_api", issue = "32838")]
pub fn new_in(alloc: A) -> Weak<T, A> {
Weak {
ptr: unsafe {
NonNull::new_unchecked(ptr::without_provenance_mut::<ArcInner<T>>(usize::MAX))
},
alloc,
}
Weak { ptr: NonNull::without_provenance(NonZeroUsize::MAX), alloc }
}
}

View file

@ -233,8 +233,7 @@ impl Layout {
#[must_use]
#[inline]
pub const fn dangling(&self) -> NonNull<u8> {
// SAFETY: align is guaranteed to be non-zero
unsafe { NonNull::new_unchecked(crate::ptr::without_provenance_mut::<u8>(self.align())) }
NonNull::without_provenance(self.align.as_nonzero())
}
/// Creates a layout describing the record that can hold a value

View file

@ -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;

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 {
($($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;
}
)+
};

View file

@ -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")
}
}
}

View file

@ -103,7 +103,8 @@
//! the time.
use core::marker::PhantomData;
use core::ptr::{self, NonNull};
use core::num::NonZeroUsize;
use core::ptr::NonNull;
use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
@ -176,7 +177,7 @@ impl Repr {
let utagged = ((code as usize) << 32) | TAG_OS;
// Safety: `TAG_OS` is not zero, so the result of the `|` is not 0.
let res = Self(
unsafe { NonNull::new_unchecked(ptr::without_provenance_mut(utagged)) },
NonNull::without_provenance(unsafe { NonZeroUsize::new_unchecked(utagged) }),
PhantomData,
);
// quickly smoke-check we encoded the right thing (This generally will
@ -193,7 +194,7 @@ impl Repr {
let utagged = ((kind as usize) << 32) | TAG_SIMPLE;
// Safety: `TAG_SIMPLE` is not zero, so the result of the `|` is not 0.
let res = Self(
unsafe { NonNull::new_unchecked(ptr::without_provenance_mut(utagged)) },
NonNull::without_provenance(unsafe { NonZeroUsize::new_unchecked(utagged) }),
PhantomData,
);
// quickly smoke-check we encoded the right thing (This generally will

View file

@ -342,6 +342,7 @@
#![feature(lazy_get)]
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_write_slice)]
#![feature(nonnull_provenance)]
#![feature(panic_can_unwind)]
#![feature(panic_internals)]
#![feature(pin_coerce_unsized_trait)]
@ -357,6 +358,7 @@
#![feature(str_internals)]
#![feature(strict_provenance_atomic_ptr)]
#![feature(sync_unsafe_cell)]
#![feature(temporary_niche_types)]
#![feature(ub_checks)]
#![feature(used_with_arg)]
// tidy-alphabetical-end

View file

@ -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());
}
}
}

View file

@ -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()) };
}
}

View file

@ -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,19 +186,18 @@ impl IntoRawSocket for OwnedSocket {
impl FromRawSocket for OwnedSocket {
#[inline]
unsafe fn from_raw_socket(socket: RawSocket) -> Self {
unsafe {
debug_assert_ne!(socket, sys::c::INVALID_SOCKET as RawSocket);
let socket = unsafe { ValidRawSocket::new_unchecked(socket) };
Self { socket }
}
}
}
#[stable(feature = "io_safety", since = "1.63.0")]
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);
}
}
}

View file

@ -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()
}
}

View file

@ -0,0 +1,344 @@
use crate::ffi::OsString;
use crate::fmt;
use crate::hash::{Hash, Hasher};
use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
use crate::path::{Path, PathBuf};
use crate::sys::time::SystemTime;
use crate::sys::unsupported;
pub struct File(!);
pub struct FileAttr(!);
pub struct ReadDir(!);
pub struct DirEntry(!);
#[derive(Clone, Debug)]
pub struct OpenOptions {}
#[derive(Copy, Clone, Debug, Default)]
pub struct FileTimes {}
pub struct FilePermissions(!);
pub struct FileType(!);
#[derive(Debug)]
pub struct DirBuilder {}
impl FileAttr {
pub fn size(&self) -> u64 {
self.0
}
pub fn perm(&self) -> FilePermissions {
self.0
}
pub fn file_type(&self) -> FileType {
self.0
}
pub fn modified(&self) -> io::Result<SystemTime> {
self.0
}
pub fn accessed(&self) -> io::Result<SystemTime> {
self.0
}
pub fn created(&self) -> io::Result<SystemTime> {
self.0
}
}
impl Clone for FileAttr {
fn clone(&self) -> FileAttr {
self.0
}
}
impl FilePermissions {
pub fn readonly(&self) -> bool {
self.0
}
pub fn set_readonly(&mut self, _readonly: bool) {
self.0
}
}
impl Clone for FilePermissions {
fn clone(&self) -> FilePermissions {
self.0
}
}
impl PartialEq for FilePermissions {
fn eq(&self, _other: &FilePermissions) -> bool {
self.0
}
}
impl Eq for FilePermissions {}
impl fmt::Debug for FilePermissions {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0
}
}
impl FileTimes {
pub fn set_accessed(&mut self, _t: SystemTime) {}
pub fn set_modified(&mut self, _t: SystemTime) {}
}
impl FileType {
pub fn is_dir(&self) -> bool {
self.0
}
pub fn is_file(&self) -> bool {
self.0
}
pub fn is_symlink(&self) -> bool {
self.0
}
}
impl Clone for FileType {
fn clone(&self) -> FileType {
self.0
}
}
impl Copy for FileType {}
impl PartialEq for FileType {
fn eq(&self, _other: &FileType) -> bool {
self.0
}
}
impl Eq for FileType {}
impl Hash for FileType {
fn hash<H: Hasher>(&self, _h: &mut H) {
self.0
}
}
impl fmt::Debug for FileType {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0
}
}
impl fmt::Debug for ReadDir {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0
}
}
impl Iterator for ReadDir {
type Item = io::Result<DirEntry>;
fn next(&mut self) -> Option<io::Result<DirEntry>> {
self.0
}
}
impl DirEntry {
pub fn path(&self) -> PathBuf {
self.0
}
pub fn file_name(&self) -> OsString {
self.0
}
pub fn metadata(&self) -> io::Result<FileAttr> {
self.0
}
pub fn file_type(&self) -> io::Result<FileType> {
self.0
}
}
impl OpenOptions {
pub fn new() -> OpenOptions {
OpenOptions {}
}
pub fn read(&mut self, _read: bool) {}
pub fn write(&mut self, _write: bool) {}
pub fn append(&mut self, _append: bool) {}
pub fn truncate(&mut self, _truncate: bool) {}
pub fn create(&mut self, _create: bool) {}
pub fn create_new(&mut self, _create_new: bool) {}
}
impl File {
pub fn open(_path: &Path, _opts: &OpenOptions) -> io::Result<File> {
unsupported()
}
pub fn file_attr(&self) -> io::Result<FileAttr> {
self.0
}
pub fn fsync(&self) -> io::Result<()> {
self.0
}
pub fn datasync(&self) -> io::Result<()> {
self.0
}
pub fn lock(&self) -> io::Result<()> {
self.0
}
pub fn lock_shared(&self) -> io::Result<()> {
self.0
}
pub fn try_lock(&self) -> io::Result<bool> {
self.0
}
pub fn try_lock_shared(&self) -> io::Result<bool> {
self.0
}
pub fn unlock(&self) -> io::Result<()> {
self.0
}
pub fn truncate(&self, _size: u64) -> io::Result<()> {
self.0
}
pub fn read(&self, _buf: &mut [u8]) -> io::Result<usize> {
self.0
}
pub fn read_vectored(&self, _bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
self.0
}
pub fn is_read_vectored(&self) -> bool {
self.0
}
pub fn read_buf(&self, _cursor: BorrowedCursor<'_>) -> io::Result<()> {
self.0
}
pub fn write(&self, _buf: &[u8]) -> io::Result<usize> {
self.0
}
pub fn write_vectored(&self, _bufs: &[IoSlice<'_>]) -> io::Result<usize> {
self.0
}
pub fn is_write_vectored(&self) -> bool {
self.0
}
pub fn flush(&self) -> io::Result<()> {
self.0
}
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
self.0
}
pub fn duplicate(&self) -> io::Result<File> {
self.0
}
pub fn set_permissions(&self, _perm: FilePermissions) -> io::Result<()> {
self.0
}
pub fn set_times(&self, _times: FileTimes) -> io::Result<()> {
self.0
}
}
impl DirBuilder {
pub fn new() -> DirBuilder {
DirBuilder {}
}
pub fn mkdir(&self, _p: &Path) -> io::Result<()> {
unsupported()
}
}
impl fmt::Debug for File {
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0
}
}
pub fn readdir(_p: &Path) -> io::Result<ReadDir> {
unsupported()
}
pub fn unlink(_p: &Path) -> io::Result<()> {
unsupported()
}
pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
unsupported()
}
pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
match perm.0 {}
}
pub fn rmdir(_p: &Path) -> io::Result<()> {
unsupported()
}
pub fn remove_dir_all(_path: &Path) -> io::Result<()> {
unsupported()
}
pub fn exists(_path: &Path) -> io::Result<bool> {
unsupported()
}
pub fn readlink(_p: &Path) -> io::Result<PathBuf> {
unsupported()
}
pub fn symlink(_original: &Path, _link: &Path) -> io::Result<()> {
unsupported()
}
pub fn link(_src: &Path, _dst: &Path) -> io::Result<()> {
unsupported()
}
pub fn stat(_p: &Path) -> io::Result<FileAttr> {
unsupported()
}
pub fn lstat(_p: &Path) -> io::Result<FileAttr> {
unsupported()
}
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
unsupported()
}
pub fn copy(_from: &Path, _to: &Path) -> io::Result<u64> {
unsupported()
}

View file

@ -15,7 +15,6 @@
pub mod args;
pub mod env;
#[path = "../unsupported/fs.rs"]
pub mod fs;
pub mod helpers;
#[path = "../unsupported/io.rs"]

View file

@ -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()
}
}

View file

@ -469,7 +469,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car
// If `compiler-rt` is available ensure that the `c` feature of the
// `compiler-builtins` crate is enabled and it's configured to learn where
// `compiler-rt` is located.
let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins {
let compiler_builtins_c_feature = if builder.config.optimized_compiler_builtins(target) {
// NOTE: this interacts strangely with `llvm-has-rust-patches`. In that case, we enforce `submodules = false`, so this is a no-op.
// But, the user could still decide to manually use an in-tree submodule.
//

View file

@ -114,6 +114,9 @@ fn print_paths(verb: &str, adjective: Option<&str>, paths: &[String]) {
} else {
println!("fmt: {verb} {len} {adjective}files");
}
if len > 1000 && !CiEnv::is_ci() {
println!("hint: if this number seems too high, try running `git fetch origin master");
}
}
pub fn format(build: &Builder<'_>, check: bool, all: bool, paths: &[PathBuf]) {

View file

@ -634,6 +634,7 @@ pub struct Target {
pub runner: Option<String>,
pub no_std: bool,
pub codegen_backends: Option<Vec<String>>,
pub optimized_compiler_builtins: Option<bool>,
}
impl Target {
@ -1219,6 +1220,7 @@ define_config! {
no_std: Option<bool> = "no-std",
codegen_backends: Option<Vec<String>> = "codegen-backends",
runner: Option<String> = "runner",
optimized_compiler_builtins: Option<bool> = "optimized-compiler-builtins",
}
}
@ -2096,6 +2098,7 @@ impl Config {
target.sanitizers = cfg.sanitizers;
target.profiler = cfg.profiler;
target.rpath = cfg.rpath;
target.optimized_compiler_builtins = cfg.optimized_compiler_builtins;
if let Some(ref backends) = cfg.codegen_backends {
let available_backends = ["llvm", "cranelift", "gcc"];
@ -2609,6 +2612,13 @@ impl Config {
self.target_config.get(&target).and_then(|t| t.rpath).unwrap_or(self.rust_rpath)
}
pub fn optimized_compiler_builtins(&self, target: TargetSelection) -> bool {
self.target_config
.get(&target)
.and_then(|t| t.optimized_compiler_builtins)
.unwrap_or(self.optimized_compiler_builtins)
}
pub fn llvm_enabled(&self, target: TargetSelection) -> bool {
self.codegen_backends(target).contains(&"llvm".to_owned())
}
@ -3162,6 +3172,9 @@ fn check_incompatible_options_for_ci_rustc(
let profiler = &ci_cfg.profiler;
err!(current_cfg.profiler, profiler, "build");
let optimized_compiler_builtins = &ci_cfg.optimized_compiler_builtins;
err!(current_cfg.optimized_compiler_builtins, optimized_compiler_builtins, "build");
}
}

View file

@ -120,6 +120,7 @@ fn override_toml() {
"--set=change-id=1".to_owned(),
"--set=rust.lto=fat".to_owned(),
"--set=rust.deny-warnings=false".to_owned(),
"--set=build.optimized-compiler-builtins=true".to_owned(),
"--set=build.gdb=\"bar\"".to_owned(),
"--set=build.tools=[\"cargo\"]".to_owned(),
"--set=llvm.build-config={\"foo\" = \"bar\"}".to_owned(),
@ -127,6 +128,7 @@ fn override_toml() {
"--set=target.x86_64-unknown-linux-gnu.rpath=false".to_owned(),
"--set=target.aarch64-unknown-linux-gnu.sanitizers=false".to_owned(),
"--set=target.aarch64-apple-darwin.runner=apple".to_owned(),
"--set=target.aarch64-apple-darwin.optimized-compiler-builtins=false".to_owned(),
]),
|&_| {
toml::from_str(
@ -167,6 +169,7 @@ runner = "x86_64-runner"
);
assert_eq!(config.gdb, Some("bar".into()), "setting string value with quotes");
assert!(!config.deny_warnings, "setting boolean value");
assert!(config.optimized_compiler_builtins, "setting boolean value");
assert_eq!(
config.tools,
Some(["cargo".to_string()].into_iter().collect()),
@ -193,7 +196,11 @@ runner = "x86_64-runner"
..Default::default()
};
let darwin = TargetSelection::from_user("aarch64-apple-darwin");
let darwin_values = Target { runner: Some("apple".into()), ..Default::default() };
let darwin_values = Target {
runner: Some("apple".into()),
optimized_compiler_builtins: Some(false),
..Default::default()
};
assert_eq!(
config.target_config,
[(x86_64, x86_64_values), (aarch64, aarch64_values), (darwin, darwin_values)]

View file

@ -325,4 +325,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
severity: ChangeSeverity::Warning,
summary: "Removed `rust.parallel-compiler` as it was deprecated in #132282 long time ago.",
},
ChangeInfo {
change_id: 135326,
severity: ChangeSeverity::Warning,
summary: "It is now possible to configure `optimized-compiler-builtins` for per target.",
},
];

View file

@ -181,10 +181,7 @@ pub fn symlink_dir(config: &Config, original: &Path, link: &Path) -> io::Result<
/// copy and remove the file otherwise
pub fn move_file<P: AsRef<Path>, Q: AsRef<Path>>(from: P, to: Q) -> io::Result<()> {
match fs::rename(&from, &to) {
// FIXME: Once `ErrorKind::CrossesDevices` is stabilized use
// if e.kind() == io::ErrorKind::CrossesDevices {
#[cfg(unix)]
Err(e) if e.raw_os_error() == Some(libc::EXDEV) => {
Err(e) if e.kind() == io::ErrorKind::CrossesDevices => {
std::fs::copy(&from, &to)?;
std::fs::remove_file(&from)
}

View file

@ -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()

View file

@ -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() {

View file

@ -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"

View file

@ -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

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 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