summaryrefslogtreecommitdiffstats
path: root/library/core/src/intrinsics.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-18 02:49:50 +0000
commit9835e2ae736235810b4ea1c162ca5e65c547e770 (patch)
tree3fcebf40ed70e581d776a8a4c65923e8ec20e026 /library/core/src/intrinsics.rs
parentReleasing progress-linux version 1.70.0+dfsg2-1~progress7.99u1. (diff)
downloadrustc-9835e2ae736235810b4ea1c162ca5e65c547e770.tar.xz
rustc-9835e2ae736235810b4ea1c162ca5e65c547e770.zip
Merging upstream version 1.71.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/core/src/intrinsics.rs')
-rw-r--r--library/core/src/intrinsics.rs79
1 files changed, 68 insertions, 11 deletions
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index a7c100e1b..f5c5dd29f 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -1187,7 +1187,7 @@ extern "rust-intrinsic" {
/// Below are common applications of `transmute` which can be replaced with safer
/// constructs.
///
- /// Turning raw bytes (`&[u8]`) into `u32`, `f64`, etc.:
+ /// Turning raw bytes (`[u8; SZ]`) into `u32`, `f64`, etc.:
///
/// ```
/// let raw_bytes = [0x78, 0x56, 0x34, 0x12];
@@ -1376,6 +1376,20 @@ extern "rust-intrinsic" {
#[rustc_nounwind]
pub fn transmute<Src, Dst>(src: Src) -> Dst;
+ /// Like [`transmute`], but even less checked at compile-time: rather than
+ /// giving an error for `size_of::<Src>() != size_of::<Dst>()`, it's
+ /// **Undefined Behaviour** at runtime.
+ ///
+ /// Prefer normal `transmute` where possible, for the extra checking, since
+ /// both do exactly the same thing at runtime, if they both compile.
+ ///
+ /// This is not expected to ever be exposed directly to users, rather it
+ /// may eventually be exposed through some more-constrained API.
+ #[cfg(not(bootstrap))]
+ #[rustc_const_stable(feature = "const_transmute", since = "1.56.0")]
+ #[rustc_nounwind]
+ pub fn transmute_unchecked<Src, Dst>(src: Src) -> Dst;
+
/// Returns `true` if the actual type given as `T` requires drop
/// glue; returns `false` if the actual type provided for `T`
/// implements `Copy`.
@@ -1399,6 +1413,10 @@ extern "rust-intrinsic" {
/// This is implemented as an intrinsic to avoid converting to and from an
/// integer, since the conversion would throw away aliasing information.
///
+ /// This can only be used with `Ptr` as a raw pointer type (`*mut` or `*const`)
+ /// to a `Sized` pointee and with `Delta` as `usize` or `isize`. Any other
+ /// instantiations may arbitrarily misbehave, and that's *not* a compiler bug.
+ ///
/// # Safety
///
/// Both the starting and resulting pointer must be either in bounds or one
@@ -1407,6 +1425,14 @@ extern "rust-intrinsic" {
/// returned value will result in undefined behavior.
///
/// The stabilized version of this intrinsic is [`pointer::offset`].
+ #[cfg(not(bootstrap))]
+ #[must_use = "returns a new pointer rather than modifying its argument"]
+ #[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
+ #[rustc_nounwind]
+ pub fn offset<Ptr, Delta>(dst: Ptr, offset: Delta) -> Ptr;
+
+ /// The bootstrap version of this is more restricted.
+ #[cfg(bootstrap)]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[rustc_const_stable(feature = "const_ptr_offset", since = "1.61.0")]
#[rustc_nounwind]
@@ -1797,14 +1823,12 @@ extern "rust-intrinsic" {
/// with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
- #[cfg(not(bootstrap))]
#[rustc_nounwind]
pub fn roundevenf32(x: f32) -> f32;
/// Returns the nearest integer to an `f64`. Rounds half-way cases to the number
/// with an even least significant digit.
///
/// This intrinsic does not have a stable counterpart.
- #[cfg(not(bootstrap))]
#[rustc_nounwind]
pub fn roundevenf64(x: f64) -> f64;
@@ -2233,13 +2257,23 @@ extern "rust-intrinsic" {
/// This is an implementation detail of [`crate::ptr::read`] and should
/// not be used anywhere else. See its comments for why this exists.
///
- /// This intrinsic can *only* be called where the argument is a local without
- /// projections (`read_via_copy(p)`, not `read_via_copy(*p)`) so that it
+ /// This intrinsic can *only* be called where the pointer is a local without
+ /// projections (`read_via_copy(ptr)`, not `read_via_copy(*ptr)`) so that it
/// trivially obeys runtime-MIR rules about derefs in operands.
+ #[rustc_const_stable(feature = "const_ptr_read", since = "1.71.0")]
+ #[rustc_nounwind]
+ pub fn read_via_copy<T>(ptr: *const T) -> T;
+
+ /// This is an implementation detail of [`crate::ptr::write`] and should
+ /// not be used anywhere else. See its comments for why this exists.
+ ///
+ /// This intrinsic can *only* be called where the pointer is a local without
+ /// projections (`write_via_move(ptr, x)`, not `write_via_move(*ptr, x)`) so
+ /// that it trivially obeys runtime-MIR rules about derefs in operands.
#[cfg(not(bootstrap))]
- #[rustc_const_unstable(feature = "const_ptr_read", issue = "80377")]
+ #[rustc_const_unstable(feature = "const_ptr_write", issue = "86302")]
#[rustc_nounwind]
- pub fn read_via_copy<T>(p: *const T) -> T;
+ pub fn write_via_move<T>(ptr: *mut T, value: T);
/// Returns the value of the discriminant for the variant in 'v';
/// if `T` has no discriminant, returns `0`.
@@ -2444,7 +2478,6 @@ extern "rust-intrinsic" {
/// This method creates a pointer to any `Some` value. If the argument is
/// `None`, an invalid within-bounds pointer (that is still acceptable for
/// constructing an empty slice) is returned.
- #[cfg(not(bootstrap))]
#[rustc_nounwind]
pub fn option_payload_ptr<T>(arg: *const Option<T>) -> *const T;
}
@@ -2460,7 +2493,7 @@ extern "rust-intrinsic" {
/// This macro should be called as `assert_unsafe_precondition!([Generics](name: Type) => Expression)`
/// where the names specified will be moved into the macro as captured variables, and defines an item
/// to call `const_eval_select` on. The tokens inside the square brackets are used to denote generics
-/// for the function declaractions and can be omitted if there is no generics.
+/// for the function declarations and can be omitted if there is no generics.
///
/// # Safety
///
@@ -2490,6 +2523,7 @@ macro_rules! assert_unsafe_precondition {
}
}
#[allow(non_snake_case)]
+ #[inline]
const fn comptime$(<$($tt)*>)?($(_:$ty),*) {}
::core::intrinsics::const_eval_select(($($i,)*), comptime, runtime);
@@ -2519,7 +2553,9 @@ pub(crate) fn is_valid_allocation_size<T>(len: usize) -> bool {
pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -> bool {
let src_usize = src.addr();
let dst_usize = dst.addr();
- let size = mem::size_of::<T>().checked_mul(count).unwrap();
+ let size = mem::size_of::<T>()
+ .checked_mul(count)
+ .expect("is_nonoverlapping: `size_of::<T>() * count` overflows a usize");
let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
// If the absolute distance between the ptrs is at least as big as the size of the buffer,
// they do not overlap.
@@ -2717,7 +2753,7 @@ pub const unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
// SAFETY: the safety contract for `copy` must be upheld by the caller.
unsafe {
assert_unsafe_precondition!(
- "ptr::copy requires that both pointer arguments are aligned aligned and non-null",
+ "ptr::copy requires that both pointer arguments are aligned and non-null",
[T](src: *const T, dst: *mut T) =>
is_aligned_and_not_null(src) && is_aligned_and_not_null(dst)
);
@@ -2796,3 +2832,24 @@ pub const unsafe fn write_bytes<T>(dst: *mut T, val: u8, count: usize) {
write_bytes(dst, val, count)
}
}
+
+/// Polyfill for bootstrap
+#[cfg(bootstrap)]
+pub const unsafe fn transmute_unchecked<Src, Dst>(src: Src) -> Dst {
+ use crate::mem::*;
+ // SAFETY: It's a transmute -- the caller promised it's fine.
+ unsafe { transmute_copy(&ManuallyDrop::new(src)) }
+}
+
+/// Polyfill for bootstrap
+#[cfg(bootstrap)]
+pub const unsafe fn write_via_move<T>(ptr: *mut T, value: T) {
+ use crate::mem::*;
+ // SAFETY: the caller must guarantee that `dst` is valid for writes.
+ // `dst` cannot overlap `src` because the caller has mutable access
+ // to `dst` while `src` is owned by this function.
+ unsafe {
+ copy_nonoverlapping::<T>(&value, ptr, 1);
+ forget(value);
+ }
+}