Skip to content

Commit 611a0e9

Browse files
author
The Miri Conjob Bot
committed
Merge from rustc
2 parents deda7d4 + 6afc3a8 commit 611a0e9

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+542
-458
lines changed

alloc/src/raw_vec.rs

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,7 @@ impl<T, A: Allocator> RawVec<T, A> {
207207
// Allocators currently return a `NonNull<[u8]>` whose length
208208
// matches the size requested. If that ever changes, the capacity
209209
// here should change to `ptr.len() / mem::size_of::<T>()`.
210-
Self {
211-
ptr: unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) },
212-
cap: unsafe { Cap(capacity) },
213-
alloc,
214-
}
210+
Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }
215211
}
216212
}
217213

@@ -239,6 +235,11 @@ impl<T, A: Allocator> RawVec<T, A> {
239235
self.ptr.as_ptr()
240236
}
241237

238+
#[inline]
239+
pub fn non_null(&self) -> NonNull<T> {
240+
NonNull::from(self.ptr)
241+
}
242+
242243
/// Gets the capacity of the allocation.
243244
///
244245
/// This will always be `usize::MAX` if `T` is zero-sized.
@@ -398,7 +399,7 @@ impl<T, A: Allocator> RawVec<T, A> {
398399
// Allocators currently return a `NonNull<[u8]>` whose length matches
399400
// the size requested. If that ever changes, the capacity here should
400401
// change to `ptr.len() / mem::size_of::<T>()`.
401-
self.ptr = unsafe { Unique::new_unchecked(ptr.cast().as_ptr()) };
402+
self.ptr = Unique::from(ptr.cast());
402403
self.cap = unsafe { Cap(cap) };
403404
}
404405

alloc/src/slice.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ pub use core::slice::{from_mut, from_ref};
5151
pub use core::slice::{from_mut_ptr_range, from_ptr_range};
5252
#[stable(feature = "rust1", since = "1.0.0")]
5353
pub use core::slice::{from_raw_parts, from_raw_parts_mut};
54-
#[stable(feature = "slice_group_by", since = "CURRENT_RUSTC_VERSION")]
54+
#[stable(feature = "slice_group_by", since = "1.77.0")]
5555
pub use core::slice::{ChunkBy, ChunkByMut};
5656
#[stable(feature = "rust1", since = "1.0.0")]
5757
pub use core::slice::{Chunks, Windows};

alloc/src/vec/cow.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ impl<'a, T: Clone> From<&'a [T]> for Cow<'a, [T]> {
1515
}
1616
}
1717

18-
#[stable(feature = "cow_from_array_ref", since = "CURRENT_RUSTC_VERSION")]
18+
#[stable(feature = "cow_from_array_ref", since = "1.77.0")]
1919
impl<'a, T: Clone, const N: usize> From<&'a [T; N]> for Cow<'a, [T]> {
2020
/// Creates a [`Borrowed`] variant of [`Cow`]
2121
/// from a reference to an array.

alloc/src/vec/into_iter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl<T, A: Allocator> IntoIter<T, A> {
136136
// struct and then overwriting &mut self.
137137
// this creates less assembly
138138
self.cap = 0;
139-
self.buf = unsafe { NonNull::new_unchecked(RawVec::NEW.ptr()) };
139+
self.buf = RawVec::NEW.non_null();
140140
self.ptr = self.buf;
141141
self.end = self.buf.as_ptr();
142142

alloc/src/vec/mod.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2861,16 +2861,16 @@ impl<T, A: Allocator> IntoIterator for Vec<T, A> {
28612861
#[inline]
28622862
fn into_iter(self) -> Self::IntoIter {
28632863
unsafe {
2864-
let mut me = ManuallyDrop::new(self);
2864+
let me = ManuallyDrop::new(self);
28652865
let alloc = ManuallyDrop::new(ptr::read(me.allocator()));
2866-
let begin = me.as_mut_ptr();
2866+
let buf = me.buf.non_null();
2867+
let begin = buf.as_ptr();
28672868
let end = if T::IS_ZST {
28682869
begin.wrapping_byte_add(me.len())
28692870
} else {
28702871
begin.add(me.len()) as *const T
28712872
};
28722873
let cap = me.buf.capacity();
2873-
let buf = NonNull::new_unchecked(begin);
28742874
IntoIter { buf, phantom: PhantomData, cap, alloc, ptr: buf, end }
28752875
}
28762876
}

core/src/array/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ impl<T, const N: usize> [T; N] {
576576
/// // We can still access the original array: it has not been moved.
577577
/// assert_eq!(strings.len(), 3);
578578
/// ```
579-
#[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")]
579+
#[stable(feature = "array_methods", since = "1.77.0")]
580580
pub fn each_ref(&self) -> [&T; N] {
581581
from_trusted_iterator(self.iter())
582582
}
@@ -595,7 +595,7 @@ impl<T, const N: usize> [T; N] {
595595
/// assert_eq!(float_refs, [&mut 0.0, &mut 2.7, &mut -1.0]);
596596
/// assert_eq!(floats, [0.0, 2.7, -1.0]);
597597
/// ```
598-
#[stable(feature = "array_methods", since = "CURRENT_RUSTC_VERSION")]
598+
#[stable(feature = "array_methods", since = "1.77.0")]
599599
pub fn each_mut(&mut self) -> [&mut T; N] {
600600
from_trusted_iterator(self.iter_mut())
601601
}

core/src/async_iter/async_iter.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ pub trait AsyncIterator {
4747
/// Rust's usual rules apply: calls must never cause undefined behavior
4848
/// (memory corruption, incorrect use of `unsafe` functions, or the like),
4949
/// regardless of the async iterator's state.
50-
#[cfg_attr(not(bootstrap), lang = "async_iterator_poll_next")]
50+
#[lang = "async_iterator_poll_next"]
5151
fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>>;
5252

5353
/// Returns the bounds on the remaining length of the async iterator.
@@ -145,7 +145,7 @@ pub trait IntoAsyncIterator {
145145
type IntoAsyncIter: AsyncIterator<Item = Self::Item>;
146146

147147
/// Converts `self` into an async iterator
148-
#[cfg_attr(not(bootstrap), lang = "into_async_iter_into_iter")]
148+
#[lang = "into_async_iter_into_iter"]
149149
fn into_async_iter(self) -> Self::IntoAsyncIter;
150150
}
151151

core/src/char/convert.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ pub(super) const unsafe fn from_u32_unchecked(i: u32) -> char {
2727
unsafe {
2828
assert_unsafe_precondition!(
2929
"invalid value for `char`",
30-
(i: u32) => char_try_from_u32(i).is_ok()
30+
(i: u32 = i) => char_try_from_u32(i).is_ok()
3131
);
3232
transmute(i)
3333
}

core/src/hint.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ pub const unsafe fn assert_unchecked(cond: bool) {
148148
unsafe {
149149
intrinsics::assert_unsafe_precondition!(
150150
"hint::assert_unchecked must never be called when the condition is false",
151-
(cond: bool) => cond,
151+
(cond: bool = cond) => cond,
152152
);
153153
crate::intrinsics::assume(cond);
154154
}

core/src/intrinsics.rs

Lines changed: 94 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656

5757
use crate::marker::DiscriminantKind;
5858
use crate::marker::Tuple;
59-
use crate::mem;
59+
use crate::mem::{self, align_of};
6060

6161
pub mod mir;
6262
pub mod simd;
@@ -947,7 +947,7 @@ extern "rust-intrinsic" {
947947
/// own, or if it does not enable any significant optimizations.
948948
///
949949
/// This intrinsic does not have a stable counterpart.
950-
#[rustc_const_stable(feature = "const_assume", since = "CURRENT_RUSTC_VERSION")]
950+
#[rustc_const_stable(feature = "const_assume", since = "1.77.0")]
951951
#[rustc_nounwind]
952952
pub fn assume(b: bool);
953953

@@ -2567,16 +2567,18 @@ extern "rust-intrinsic" {
25672567
/// matter what*.
25682568
#[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")]
25692569
#[rustc_nounwind]
2570-
#[cfg(not(bootstrap))]
25712570
pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
2571+
2572+
#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
2573+
#[rustc_safe_intrinsic]
2574+
#[cfg(not(bootstrap))]
2575+
pub(crate) fn debug_assertions() -> bool;
25722576
}
25732577

2574-
// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable`
2575-
// and thus compiling stage0 core doesn't work.
2576-
#[rustc_const_stable(feature = "is_val_statically_known", since = "0.0.0")]
25772578
#[cfg(bootstrap)]
2578-
pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
2579-
false
2579+
#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
2580+
pub(crate) const fn debug_assertions() -> bool {
2581+
cfg!(debug_assertions)
25802582
}
25812583

25822584
// Some functions are defined here because they accidentally got made
@@ -2587,10 +2589,27 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
25872589
/// Check that the preconditions of an unsafe function are followed, if debug_assertions are on,
25882590
/// and only at runtime.
25892591
///
2590-
/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)`
2591-
/// where the names specified will be moved into the macro as captured variables, and defines an item
2592-
/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics
2593-
/// for the function declarations and can be omitted if there is no generics.
2592+
/// This macro should be called as
2593+
/// `assert_unsafe_precondition!((expr => name: Type, expr => name: Type) => Expression)`
2594+
/// where each `expr` will be evaluated and passed in as function argument `name: Type`. Then all
2595+
/// those arguments are passed to a function via [`const_eval_select`].
2596+
///
2597+
/// These checks are behind a condition which is evaluated at codegen time, not expansion time like
2598+
/// [`debug_assert`]. This means that a standard library built with optimizations and debug
2599+
/// assertions disabled will have these checks optimized out of its monomorphizations, but if a
2600+
/// a caller of the standard library has debug assertions enabled and monomorphizes an expansion of
2601+
/// this macro, that monomorphization will contain the check.
2602+
///
2603+
/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and
2604+
/// implementation to mitigate their compile-time overhead. The runtime function that we
2605+
/// [`const_eval_select`] to is monomorphic, `#[inline(never)]`, and `#[rustc_nounwind]`. That
2606+
/// combination of properties ensures that the code for the checks is only compiled once, and has a
2607+
/// minimal impact on the caller's code size.
2608+
///
2609+
/// Caller should also introducing any other `let` bindings or any code outside this macro in order
2610+
/// to call it. Since the precompiled standard library is built with full debuginfo and these
2611+
/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough
2612+
/// debuginfo to have a measurable compile-time impact on debug builds.
25942613
///
25952614
/// # Safety
25962615
///
@@ -2604,26 +2623,24 @@ pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
26042623
///
26052624
/// So in a sense it is UB if this macro is useful, but we expect callers of `unsafe fn` to make
26062625
/// the occasional mistake, and this check should help them figure things out.
2607-
#[allow_internal_unstable(const_eval_select)] // permit this to be called in stably-const fn
2626+
#[allow_internal_unstable(const_eval_select, delayed_debug_assertions)] // permit this to be called in stably-const fn
26082627
macro_rules! assert_unsafe_precondition {
2609-
($name:expr, $([$($tt:tt)*])?($($i:ident:$ty:ty),*$(,)?) => $e:expr $(,)?) => {
2610-
if cfg!(debug_assertions) {
2611-
// allow non_snake_case to allow capturing const generics
2612-
#[allow(non_snake_case)]
2613-
#[inline(always)]
2614-
fn runtime$(<$($tt)*>)?($($i:$ty),*) {
2628+
($message:expr, ($($name:ident:$ty:ty = $arg:expr),*$(,)?) => $e:expr $(,)?) => {
2629+
{
2630+
#[inline(never)]
2631+
#[rustc_nounwind]
2632+
fn precondition_check($($name:$ty),*) {
26152633
if !$e {
2616-
// don't unwind to reduce impact on code size
26172634
::core::panicking::panic_nounwind(
2618-
concat!("unsafe precondition(s) violated: ", $name)
2635+
concat!("unsafe precondition(s) violated: ", $message)
26192636
);
26202637
}
26212638
}
2622-
#[allow(non_snake_case)]
2623-
#[inline]
2624-
const fn comptime$(<$($tt)*>)?($(_:$ty),*) {}
2639+
const fn comptime($(_:$ty),*) {}
26252640

2626-
::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime);
2641+
if ::core::intrinsics::debug_assertions() {
2642+
::core::intrinsics::const_eval_select(($($arg,)*), comptime, precondition_check);
2643+
}
26272644
}
26282645
};
26292646
}
@@ -2632,30 +2649,47 @@ pub(crate) use assert_unsafe_precondition;
26322649
/// Checks whether `ptr` is properly aligned with respect to
26332650
/// `align_of::<T>()`.
26342651
#[inline]
2635-
pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
2636-
!ptr.is_null() && ptr.is_aligned()
2652+
pub(crate) fn is_aligned_and_not_null(ptr: *const (), align: usize) -> bool {
2653+
!ptr.is_null() && ptr.is_aligned_to(align)
26372654
}
26382655

2639-
/// Checks whether an allocation of `len` instances of `T` exceeds
2640-
/// the maximum allowed allocation size.
26412656
#[inline]
2642-
pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
2643-
let max_len = const {
2644-
let size = crate::mem::size_of::<T>();
2645-
if size == 0 { usize::MAX } else { isize::MAX as usize / size }
2646-
};
2657+
pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool {
2658+
let max_len = if size == 0 { usize::MAX } else { isize::MAX as usize / size };
26472659
len <= max_len
26482660
}
26492661

2662+
pub(crate) fn is_nonoverlapping_mono(
2663+
src: *const (),
2664+
dst: *const (),
2665+
size: usize,
2666+
count: usize,
2667+
) -> bool {
2668+
let src_usize = src.addr();
2669+
let dst_usize = dst.addr();
2670+
let Some(size) = size.checked_mul(count) else {
2671+
crate::panicking::panic_nounwind(
2672+
"is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
2673+
)
2674+
};
2675+
let diff = src_usize.abs_diff(dst_usize);
2676+
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
2677+
// they do not overlap.
2678+
diff >= size
2679+
}
2680+
26502681
/// Checks whether the regions of memory starting at `src` and `dst` of size
26512682
/// `count * size_of::<T>()` do *not* overlap.
26522683
#[inline]
26532684
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
26542685
let src_usize = src.addr();
26552686
let dst_usize = dst.addr();
2656-
let size = mem::size_of::<T>()
2657-
.checked_mul(count)
2658-
.expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize");
2687+
let Some(size) = mem::size_of::<T>().checked_mul(count) else {
2688+
// Use panic_nounwind instead of Option::expect, so that this function is nounwind.
2689+
crate::panicking::panic_nounwind(
2690+
"is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
2691+
)
2692+
};
26592693
let diff = src_usize.abs_diff(dst_usize);
26602694
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
26612695
// they do not overlap.
@@ -2766,10 +2800,16 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
27662800
assert_unsafe_precondition!(
27672801
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
27682802
and the specified memory ranges do not overlap",
2769-
[T](src: *const T, dst: *mut T, count: usize) =>
2770-
is_aligned_and_not_null(src)
2771-
&& is_aligned_and_not_null(dst)
2772-
&& is_nonoverlapping(src, dst, count)
2803+
(
2804+
src: *const () = src as *const (),
2805+
dst: *mut () = dst as *mut (),
2806+
size: usize = size_of::<T>(),
2807+
align: usize = align_of::<T>(),
2808+
count: usize = count,
2809+
) =>
2810+
is_aligned_and_not_null(src, align)
2811+
&& is_aligned_and_not_null(dst, align)
2812+
&& is_nonoverlapping_mono(src, dst, size, count)
27732813
);
27742814
copy_nonoverlapping(src, dst, count)
27752815
}
@@ -2859,9 +2899,15 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
28592899
// SAFETY: the safety contract for `copy` must be upheld by the caller.
28602900
unsafe {
28612901
assert_unsafe_precondition!(
2862-
"ptr::copy requires that both pointer arguments are aligned and non-null",
2863-
[T](src: *const T, dst: *mut T) =>
2864-
is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)
2902+
"ptr::copy_nonoverlapping requires that both pointer arguments are aligned and non-null \
2903+
and the specified memory ranges do not overlap",
2904+
(
2905+
src: *const () = src as *const (),
2906+
dst: *mut () = dst as *mut (),
2907+
align: usize = align_of::<T>(),
2908+
) =>
2909+
is_aligned_and_not_null(src, align)
2910+
&& is_aligned_and_not_null(dst, align)
28652911
);
28662912
copy(src, dst, count)
28672913
}
@@ -2934,7 +2980,10 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
29342980
unsafe {
29352981
assert_unsafe_precondition!(
29362982
"ptr::write_bytes requires that the destination pointer is aligned and non-null",
2937-
[T](dst: *mut T) => is_aligned_and_not_null(dst)
2983+
(
2984+
addr: *const () = dst as *const (),
2985+
align: usize = align_of::<T>(),
2986+
) => is_aligned_and_not_null(addr, align)
29382987
);
29392988
write_bytes(dst, val, count)
29402989
}

0 commit comments

Comments
 (0)