Skip to content

Commit a5c4da3

Browse files
committed
Merge from rustc
2 parents 6a192fb + 669e05f commit a5c4da3

File tree

38 files changed

+1041
-393
lines changed

38 files changed

+1041
-393
lines changed

alloc/src/boxed/thin.rs

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,26 @@ impl<T> ThinBox<T> {
6767
let ptr = WithOpaqueHeader::new(meta, value);
6868
ThinBox { ptr, _marker: PhantomData }
6969
}
70+
71+
/// Moves a type to the heap with its [`Metadata`] stored in the heap allocation instead of on
72+
/// the stack. Returns an error if allocation fails, instead of aborting.
73+
///
74+
/// # Examples
75+
///
76+
/// ```
77+
/// #![feature(allocator_api)]
78+
/// #![feature(thin_box)]
79+
/// use std::boxed::ThinBox;
80+
///
81+
/// let five = ThinBox::try_new(5)?;
82+
/// # Ok::<(), std::alloc::AllocError>(())
83+
/// ```
84+
///
85+
/// [`Metadata`]: core::ptr::Pointee::Metadata
86+
pub fn try_new(value: T) -> Result<Self, core::alloc::AllocError> {
87+
let meta = ptr::metadata(&value);
88+
WithOpaqueHeader::try_new(meta, value).map(|ptr| ThinBox { ptr, _marker: PhantomData })
89+
}
7090
}
7191

7292
#[unstable(feature = "thin_box", issue = "92791")]
@@ -179,6 +199,10 @@ impl WithOpaqueHeader {
179199
let ptr = WithHeader::new(header, value);
180200
Self(ptr.0)
181201
}
202+
203+
fn try_new<H, T>(header: H, value: T) -> Result<Self, core::alloc::AllocError> {
204+
WithHeader::try_new(header, value).map(|ptr| Self(ptr.0))
205+
}
182206
}
183207

184208
impl<H> WithHeader<H> {
@@ -224,6 +248,46 @@ impl<H> WithHeader<H> {
224248
}
225249
}
226250

251+
/// Non-panicking version of `new`.
252+
/// Any error is returned as `Err(core::alloc::AllocError)`.
253+
fn try_new<T>(header: H, value: T) -> Result<WithHeader<H>, core::alloc::AllocError> {
254+
let value_layout = Layout::new::<T>();
255+
let Ok((layout, value_offset)) = Self::alloc_layout(value_layout) else {
256+
return Err(core::alloc::AllocError);
257+
};
258+
259+
unsafe {
260+
// Note: It's UB to pass a layout with a zero size to `alloc::alloc`, so
261+
// we use `layout.dangling()` for this case, which should have a valid
262+
// alignment for both `T` and `H`.
263+
let ptr = if layout.size() == 0 {
264+
// Some paranoia checking, mostly so that the ThinBox tests are
265+
// more able to catch issues.
266+
debug_assert!(
267+
value_offset == 0 && mem::size_of::<T>() == 0 && mem::size_of::<H>() == 0
268+
);
269+
layout.dangling()
270+
} else {
271+
let ptr = alloc::alloc(layout);
272+
if ptr.is_null() {
273+
return Err(core::alloc::AllocError);
274+
}
275+
276+
// Safety:
277+
// - The size is at least `aligned_header_size`.
278+
let ptr = ptr.add(value_offset) as *mut _;
279+
280+
NonNull::new_unchecked(ptr)
281+
};
282+
283+
let result = WithHeader(ptr, PhantomData);
284+
ptr::write(result.header(), header);
285+
ptr::write(result.value().cast(), value);
286+
287+
Ok(result)
288+
}
289+
}
290+
227291
// Safety:
228292
// - Assumes that either `value` can be dereferenced, or is the
229293
// `NonNull::dangling()` we use when both `T` and `H` are ZSTs.

alloc/src/fmt.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@
188188
//! * `#X` - precedes the argument with a `0x`
189189
//! * `#b` - precedes the argument with a `0b`
190190
//! * `#o` - precedes the argument with a `0o`
191+
//!
192+
//! See [Formatting traits](#formatting-traits) for a description of what the `?`, `x`, `X`,
193+
//! `b`, and `o` flags do.
194+
//!
191195
//! * `0` - This is used to indicate for integer formats that the padding to `width` should
192196
//! both be done with a `0` character as well as be sign-aware. A format
193197
//! like `{:08}` would yield `00000001` for the integer `1`, while the
@@ -197,6 +201,7 @@
197201
//! and before the digits. When used together with the `#` flag, a similar
198202
//! rule applies: padding zeros are inserted after the prefix but before
199203
//! the digits. The prefix is included in the total width.
204+
//! This flag overrides the [fill character and alignment flag](#fillalignment).
200205
//!
201206
//! ## Precision
202207
//!

core/src/cell.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,9 +237,9 @@
237237

238238
use crate::cmp::Ordering;
239239
use crate::fmt::{self, Debug, Display};
240-
use crate::intrinsics::is_nonoverlapping;
240+
use crate::intrinsics;
241241
use crate::marker::{PhantomData, Unsize};
242-
use crate::mem;
242+
use crate::mem::{self, size_of};
243243
use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn};
244244
use crate::ptr::{self, NonNull};
245245

@@ -435,11 +435,15 @@ impl<T> Cell<T> {
435435
#[inline]
436436
#[stable(feature = "move_cell", since = "1.17.0")]
437437
pub fn swap(&self, other: &Self) {
438+
fn is_nonoverlapping<T>(src: *const T, dst: *const T) -> bool {
439+
intrinsics::is_nonoverlapping(src.cast(), dst.cast(), size_of::<T>(), 1)
440+
}
441+
438442
if ptr::eq(self, other) {
439443
// Swapping wouldn't change anything.
440444
return;
441445
}
442-
if !is_nonoverlapping(self, other, 1) {
446+
if !is_nonoverlapping(self, other) {
443447
// See <https://github.com/rust-lang/rust/issues/80778> for why we need to stop here.
444448
panic!("`Cell::swap` on overlapping non-identical `Cell`s");
445449
}

core/src/ffi/c_str.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ use crate::str;
8888
// want `repr(transparent)` but we don't want it to show up in rustdoc, so we hide it under
8989
// `cfg(doc)`. This is an ad-hoc implementation of attribute privacy.
9090
#[cfg_attr(not(doc), repr(transparent))]
91+
#[allow(clippy::derived_hash_with_manual_eq)]
9192
pub struct CStr {
9293
// FIXME: this should not be represented with a DST slice but rather with
9394
// just a raw `c_char` along with some form of marker to make

core/src/intrinsics.rs

Lines changed: 25 additions & 33 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::{self, align_of};
59+
use crate::mem::align_of;
6060

6161
pub mod mir;
6262
pub mod simd;
@@ -1027,7 +1027,7 @@ extern "rust-intrinsic" {
10271027

10281028
/// The size of the referenced value in bytes.
10291029
///
1030-
/// The stabilized version of this intrinsic is [`mem::size_of_val`].
1030+
/// The stabilized version of this intrinsic is [`crate::mem::size_of_val`].
10311031
#[rustc_const_unstable(feature = "const_size_of_val", issue = "46571")]
10321032
#[rustc_nounwind]
10331033
pub fn size_of_val<T: ?Sized>(_: *const T) -> usize;
@@ -1107,7 +1107,7 @@ extern "rust-intrinsic" {
11071107

11081108
/// Moves a value out of scope without running drop glue.
11091109
///
1110-
/// This exists solely for [`mem::forget_unsized`]; normal `forget` uses
1110+
/// This exists solely for [`crate::mem::forget_unsized`]; normal `forget` uses
11111111
/// `ManuallyDrop` instead.
11121112
///
11131113
/// Note that, unlike most intrinsics, this is safe to call;
@@ -1233,7 +1233,7 @@ extern "rust-intrinsic" {
12331233
/// Depending on what the code is doing, the following alternatives are preferable to
12341234
/// pointer-to-integer transmutation:
12351235
/// - If the code just wants to store data of arbitrary type in some buffer and needs to pick a
1236-
/// type for that buffer, it can use [`MaybeUninit`][mem::MaybeUninit].
1236+
/// type for that buffer, it can use [`MaybeUninit`][crate::mem::MaybeUninit].
12371237
/// - If the code actually wants to work on the address the pointer points to, it can use `as`
12381238
/// casts or [`ptr.addr()`][pointer::addr].
12391239
///
@@ -2317,7 +2317,7 @@ extern "rust-intrinsic" {
23172317
/// Therefore, implementations must not require the user to uphold
23182318
/// any safety invariants.
23192319
///
2320-
/// The to-be-stabilized version of this intrinsic is [`mem::variant_count`].
2320+
/// The to-be-stabilized version of this intrinsic is [`crate::mem::variant_count`].
23212321
#[rustc_const_unstable(feature = "variant_count", issue = "73662")]
23222322
#[rustc_safe_intrinsic]
23232323
#[rustc_nounwind]
@@ -2569,6 +2569,19 @@ extern "rust-intrinsic" {
25692569
#[rustc_nounwind]
25702570
pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
25712571

2572+
/// Returns the value of `cfg!(debug_assertions)`, but after monomorphization instead of in
2573+
/// macro expansion.
2574+
///
2575+
/// This always returns `false` in const eval and Miri. The interpreter provides better
2576+
/// diagnostics than the checks that this is used to implement. However, this means
2577+
/// you should only be using this intrinsic to guard requirements that, if violated,
2578+
/// immediately lead to UB. Otherwise, const-eval and Miri will miss out on those
2579+
/// checks entirely.
2580+
///
2581+
/// Since this is evaluated after monomorphization, branching on this value can be used to
2582+
/// implement debug assertions that are included in the precompiled standard library, but can
2583+
/// be optimized out by builds that monomorphize the standard library code with debug
2584+
/// assertions disabled. This intrinsic is primarily used by [`assert_unsafe_precondition`].
25722585
#[rustc_const_unstable(feature = "delayed_debug_assertions", issue = "none")]
25732586
#[rustc_safe_intrinsic]
25742587
#[cfg(not(bootstrap))]
@@ -2597,7 +2610,7 @@ pub(crate) const fn debug_assertions() -> bool {
25972610
/// These checks are behind a condition which is evaluated at codegen time, not expansion time like
25982611
/// [`debug_assert`]. This means that a standard library built with optimizations and debug
25992612
/// 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
2613+
/// caller of the standard library has debug assertions enabled and monomorphizes an expansion of
26012614
/// this macro, that monomorphization will contain the check.
26022615
///
26032616
/// Since these checks cannot be optimized out in MIR, some care must be taken in both call and
@@ -2606,8 +2619,8 @@ pub(crate) const fn debug_assertions() -> bool {
26062619
/// combination of properties ensures that the code for the checks is only compiled once, and has a
26072620
/// minimal impact on the caller's code size.
26082621
///
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
2622+
/// Callers should also avoid introducing any other `let` bindings or any code outside this macro in
2623+
/// order to call it. Since the precompiled standard library is built with full debuginfo and these
26112624
/// variables cannot be optimized out in MIR, an innocent-looking `let` can produce enough
26122625
/// debuginfo to have a measurable compile-time impact on debug builds.
26132626
///
@@ -2659,33 +2672,12 @@ pub(crate) fn is_valid_allocation_size(size: usize, len: usize) -> bool {
26592672
len <= max_len
26602673
}
26612674

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-
26812675
/// Checks whether the regions of memory starting at `src` and `dst` of size
2682-
/// `count * size_of::<T>()` do *not* overlap.
2683-
#[inline]
2684-
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
2676+
/// `count * size` do *not* overlap.
2677+
pub(crate) fn is_nonoverlapping(src: *const (), dst: *const (), size: usize, count: usize) -> bool {
26852678
let src_usize = src.addr();
26862679
let dst_usize = dst.addr();
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.
2680+
let Some(size) = size.checked_mul(count) else {
26892681
crate::panicking::panic_nounwind(
26902682
"is_nonoverlapping: `size_of::<T>() * count` overflows a usize",
26912683
)
@@ -2809,7 +2801,7 @@ pub const unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: us
28092801
) =>
28102802
is_aligned_and_not_null(src, align)
28112803
&& is_aligned_and_not_null(dst, align)
2812-
&& is_nonoverlapping_mono(src, dst, size, count)
2804+
&& is_nonoverlapping(src, dst, size, count)
28132805
);
28142806
copy_nonoverlapping(src, dst, count)
28152807
}

core/src/intrinsics/simd.rs

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,27 @@ extern "platform-intrinsic" {
190190
///
191191
/// `T` must be a vector.
192192
///
193-
/// `U` must be a const array of `i32`s.
193+
/// `U` must be a **const** array of `i32`s. This means it must either refer to a named
194+
/// const or be given as an inline const expression (`const { ... }`).
194195
///
195196
/// `V` must be a vector with the same element type as `T` and the same length as `U`.
196197
///
197-
/// Concatenates `x` and `y`, then returns a new vector such that each element is selected from
198-
/// the concatenation by the matching index in `idx`.
198+
/// Returns a new vector such that element `i` is selected from `xy[idx[i]]`, where `xy`
199+
/// is the concatenation of `x` and `y`. It is a compile-time error if `idx[i]` is out-of-bounds
200+
/// of `xy`.
199201
pub fn simd_shuffle<T, U, V>(x: T, y: T, idx: U) -> V;
200202

203+
/// Shuffle two vectors by const indices.
204+
///
205+
/// `T` must be a vector.
206+
///
207+
/// `U` must be a vector with the same element type as `T` and the same length as `IDX`.
208+
///
209+
/// Returns a new vector such that element `i` is selected from `xy[IDX[i]]`, where `xy`
210+
/// is the concatenation of `x` and `y`. It is a compile-time error if `IDX[i]` is out-of-bounds
211+
/// of `xy`.
212+
pub fn simd_shuffle_generic<T, U, const IDX: &'static [u32]>(x: T, y: T) -> U;
213+
201214
/// Read a vector of pointers.
202215
///
203216
/// `T` must be a vector.
@@ -232,6 +245,9 @@ extern "platform-intrinsic" {
232245
/// corresponding value in `val` to the pointer.
233246
/// Otherwise if the corresponding value in `mask` is `0`, do nothing.
234247
///
248+
/// The stores happen in left-to-right order.
249+
/// (This is relevant in case two of the stores overlap.)
250+
///
235251
/// # Safety
236252
/// Unmasked values in `T` must be writeable as if by `<ptr>::write` (e.g. aligned to the element
237253
/// type).
@@ -468,4 +484,36 @@ extern "platform-intrinsic" {
468484
///
469485
/// `T` must be a vector of integers.
470486
pub fn simd_cttz<T>(x: T) -> T;
487+
488+
/// Round up each element to the next highest integer-valued float.
489+
///
490+
/// `T` must be a vector of floats.
491+
pub fn simd_ceil<T>(x: T) -> T;
492+
493+
/// Round down each element to the next lowest integer-valued float.
494+
///
495+
/// `T` must be a vector of floats.
496+
pub fn simd_floor<T>(x: T) -> T;
497+
498+
/// Round each element to the closest integer-valued float.
499+
/// Ties are resolved by rounding away from 0.
500+
///
501+
/// `T` must be a vector of floats.
502+
pub fn simd_round<T>(x: T) -> T;
503+
504+
/// Return the integer part of each element as an integer-valued float.
505+
/// In other words, non-integer values are truncated towards zero.
506+
///
507+
/// `T` must be a vector of floats.
508+
pub fn simd_trunc<T>(x: T) -> T;
509+
510+
/// Takes the square root of each element.
511+
///
512+
/// `T` must be a vector of floats.
513+
pub fn simd_fsqrt<T>(x: T) -> T;
514+
515+
/// Computes `(x*y) + z` for each element, but without any intermediate rounding.
516+
///
517+
/// `T` must be a vector of floats.
518+
pub fn simd_fma<T>(x: T, y: T, z: T) -> T;
471519
}

core/src/num/f32.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -462,6 +462,7 @@ impl f32 {
462462
/// and target platforms isn't guaranteed.
463463
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
464464
#[rustc_diagnostic_item = "f32_nan"]
465+
#[allow(clippy::eq_op)]
465466
pub const NAN: f32 = 0.0_f32 / 0.0_f32;
466467
/// Infinity (∞).
467468
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
@@ -483,6 +484,7 @@ impl f32 {
483484
#[stable(feature = "rust1", since = "1.0.0")]
484485
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
485486
#[inline]
487+
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
486488
pub const fn is_nan(self) -> bool {
487489
self != self
488490
}

core/src/num/f64.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,7 @@ impl f64 {
461461
/// and target platforms isn't guaranteed.
462462
#[rustc_diagnostic_item = "f64_nan"]
463463
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
464+
#[allow(clippy::eq_op)]
464465
pub const NAN: f64 = 0.0_f64 / 0.0_f64;
465466
/// Infinity (∞).
466467
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
@@ -482,6 +483,7 @@ impl f64 {
482483
#[stable(feature = "rust1", since = "1.0.0")]
483484
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
484485
#[inline]
486+
#[allow(clippy::eq_op)] // > if you intended to check if the operand is NaN, use `.is_nan()` instead :)
485487
pub const fn is_nan(self) -> bool {
486488
self != self
487489
}

core/src/option.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,7 @@ use crate::{
567567
#[rustc_diagnostic_item = "Option"]
568568
#[lang = "Option"]
569569
#[stable(feature = "rust1", since = "1.0.0")]
570+
#[allow(clippy::derived_hash_with_manual_eq)] // PartialEq is specialized
570571
pub enum Option<T> {
571572
/// No value.
572573
#[lang = "None"]

0 commit comments

Comments
 (0)