]> git.lizzy.rs Git - rust.git/blobdiff - src/libcore/intrinsics.rs
Rollup merge of #68438 - Aaron1011:fix/tait-non-defining, r=estebank
[rust.git] / src / libcore / intrinsics.rs
index b02acce2d00bb17b6e551dd02c450d8092d12579..416c73f50bd89661bab7cfa0d0609563dbd91bd8 100644 (file)
@@ -1,6 +1,22 @@
 //! Compiler intrinsics.
 //!
 //! The corresponding definitions are in `librustc_codegen_llvm/intrinsic.rs`.
+//! The corresponding const implementations are in `librustc_mir/interpret/intrinsics.rs`
+//!
+//! # Const intrinsics
+//!
+//! Note: any changes to the constness of intrinsics should be discussed with the language team.
+//! This includes changes in the stability of the constness.
+//!
+//! In order to make an intrinsic usable at compile-time, one needs to copy the implementation
+//! from https://github.com/rust-lang/miri/blob/master/src/shims/intrinsics.rs to
+//! `librustc_mir/interpret/intrinsics.rs` and add a
+//! `#[rustc_const_unstable(feature = "foo", issue = "01234")]` to the intrinsic.
+//!
+//! If an intrinsic is supposed to be used from a `const fn` with a `rustc_const_stable` attribute,
+//! the intrinsic's attribute must be `rustc_const_stable`, too. Such a change should not be done
+//! without T-lang consulation, because it bakes a feature into the language that cannot be
+//! replicated in user code without compiler support.
 //!
 //! # Volatiles
 //!
 //!   guaranteed to happen in order. This is the standard mode for working
 //!   with atomic types and is equivalent to Java's `volatile`.
 
-#![unstable(feature = "core_intrinsics",
-            reason = "intrinsics are unlikely to ever be stabilized, instead \
+#![unstable(
+    feature = "core_intrinsics",
+    reason = "intrinsics are unlikely to ever be stabilized, instead \
                       they should be used through stabilized interfaces \
                       in the rest of the standard library",
-            issue = "0")]
+    issue = "none"
+)]
 #![allow(missing_docs)]
 
 use crate::mem;
 
 #[stable(feature = "drop_in_place", since = "1.8.0")]
-#[rustc_deprecated(reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
-                   since = "1.18.0")]
+#[rustc_deprecated(
+    reason = "no longer an intrinsic - use `ptr::drop_in_place` directly",
+    since = "1.18.0"
+)]
 pub use crate::ptr::drop_in_place;
 
 extern "rust-intrinsic" {
     ///
     /// The stabilized version of this intrinsic is
     /// [`std::mem::size_of`](../../std/mem/fn.size_of.html).
+    #[rustc_const_stable(feature = "const_size_of", since = "1.40.0")]
     pub fn size_of<T>() -> usize;
 
     /// Moves a value to an uninitialized memory location.
     /// Drop glue is not run on the destination.
     pub fn move_val_init<T>(dst: *mut T, src: T);
 
+    #[rustc_const_stable(feature = "const_min_align_of", since = "1.40.0")]
     pub fn min_align_of<T>() -> usize;
+    #[rustc_const_unstable(feature = "const_pref_align_of", issue = "none")]
     pub fn pref_align_of<T>() -> usize;
 
     /// The size of the referenced value in bytes.
     pub fn min_align_of_val<T: ?Sized>(_: &T) -> usize;
 
     /// Gets a static string slice containing the name of a type.
+    #[rustc_const_unstable(feature = "const_type_name", issue = "none")]
     pub fn type_name<T: ?Sized>() -> &'static str;
 
     /// Gets an identifier which is globally unique to the specified type. This
     /// function will return the same value for a type regardless of whichever
     /// crate it is invoked in.
+    #[rustc_const_unstable(feature = "const_type_id", issue = "none")]
     pub fn type_id<T: ?Sized + 'static>() -> u64;
 
     /// A guard for unsafe functions that cannot ever be executed if `T` is uninhabited:
     pub fn panic_if_uninhabited<T>();
 
     /// Gets a reference to a static `Location` indicating where it was called.
+    #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
     pub fn caller_location() -> &'static crate::panic::Location<'static>;
 
     /// Creates a value initialized to zero.
     /// which is unsafe unless `T` is `Copy`. Also, even if T is
     /// `Copy`, an all-zero value may not correspond to any legitimate
     /// state for the type in question.
-    #[unstable(feature = "core_intrinsics",
-               reason = "intrinsics are unlikely to ever be stabilized, instead \
+    #[unstable(
+        feature = "core_intrinsics",
+        reason = "intrinsics are unlikely to ever be stabilized, instead \
                          they should be used through stabilized interfaces \
                          in the rest of the standard library",
-               issue = "0")]
-    #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned",
-                       since = "1.38.0")]
+        issue = "none"
+    )]
+    #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
     pub fn init<T>() -> T;
 
     /// Creates an uninitialized value.
     /// state, which means it may claim either dropped or
     /// undropped. In the general case one must use `ptr::write` to
     /// initialize memory previous set to the result of `uninit`.
-    #[unstable(feature = "core_intrinsics",
-               reason = "intrinsics are unlikely to ever be stabilized, instead \
+    #[unstable(
+        feature = "core_intrinsics",
+        reason = "intrinsics are unlikely to ever be stabilized, instead \
                          they should be used through stabilized interfaces \
                          in the rest of the standard library",
-               issue = "0")]
-    #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned",
-                       since = "1.38.0")]
+        issue = "none"
+    )]
+    #[rustc_deprecated(reason = "superseded by MaybeUninit, removal planned", since = "1.38.0")]
     pub fn uninit<T>() -> T;
 
     /// Moves a value out of scope without running drop glue.
     ///
     /// The stabilized version of this intrinsic is
     /// [`std::mem::needs_drop`](../../std/mem/fn.needs_drop.html).
+    #[rustc_const_stable(feature = "const_needs_drop", since = "1.40.0")]
     pub fn needs_drop<T>() -> bool;
 
     /// Calculates the offset from a pointer.
     ///
     /// The volatile parameter is set to `true`, so it will not be optimized out
     /// unless size is equal to zero.
-    pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
-                                                  count: usize);
+    pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
     /// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
     /// a size of `count` * `size_of::<T>()` and an alignment of
     /// `min_align_of::<T>()`
@@ -1148,8 +1176,8 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// https://github.com/rust-lang/rust/issues/10184
     pub fn float_to_int_approx_unchecked<Float, Int>(value: Float) -> Int;
 
-
     /// Returns the number of bits set in an integer type `T`
+    #[rustc_const_stable(feature = "const_ctpop", since = "1.40.0")]
     pub fn ctpop<T>(x: T) -> T;
 
     /// Returns the number of leading unset bits (zeroes) in an integer type `T`.
@@ -1177,6 +1205,7 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// let num_leading = ctlz(x);
     /// assert_eq!(num_leading, 16);
     /// ```
+    #[rustc_const_stable(feature = "const_ctlz", since = "1.40.0")]
     pub fn ctlz<T>(x: T) -> T;
 
     /// Like `ctlz`, but extra-unsafe as it returns `undef` when
@@ -1193,6 +1222,7 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// let num_leading = unsafe { ctlz_nonzero(x) };
     /// assert_eq!(num_leading, 3);
     /// ```
+    #[rustc_const_unstable(feature = "constctlz", issue = "none")]
     pub fn ctlz_nonzero<T>(x: T) -> T;
 
     /// Returns the number of trailing unset bits (zeroes) in an integer type `T`.
@@ -1220,6 +1250,7 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// let num_trailing = cttz(x);
     /// assert_eq!(num_trailing, 16);
     /// ```
+    #[rustc_const_stable(feature = "const_cttz", since = "1.40.0")]
     pub fn cttz<T>(x: T) -> T;
 
     /// Like `cttz`, but extra-unsafe as it returns `undef` when
@@ -1236,30 +1267,36 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// let num_trailing = unsafe { cttz_nonzero(x) };
     /// assert_eq!(num_trailing, 3);
     /// ```
+    #[rustc_const_unstable(feature = "const_cttz", issue = "none")]
     pub fn cttz_nonzero<T>(x: T) -> T;
 
     /// Reverses the bytes in an integer type `T`.
+    #[rustc_const_stable(feature = "const_bswap", since = "1.40.0")]
     pub fn bswap<T>(x: T) -> T;
 
     /// Reverses the bits in an integer type `T`.
+    #[rustc_const_stable(feature = "const_bitreverse", since = "1.40.0")]
     pub fn bitreverse<T>(x: T) -> T;
 
     /// Performs checked integer addition.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_add` method. For example,
     /// [`std::u32::overflowing_add`](../../std/primitive.u32.html#method.overflowing_add)
+    #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn add_with_overflow<T>(x: T, y: T) -> (T, bool);
 
     /// Performs checked integer subtraction
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_sub` method. For example,
     /// [`std::u32::overflowing_sub`](../../std/primitive.u32.html#method.overflowing_sub)
+    #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn sub_with_overflow<T>(x: T, y: T) -> (T, bool);
 
     /// Performs checked integer multiplication
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `overflowing_mul` method. For example,
     /// [`std::u32::overflowing_mul`](../../std/primitive.u32.html#method.overflowing_mul)
+    #[rustc_const_stable(feature = "const_int_overflow", since = "1.40.0")]
     pub fn mul_with_overflow<T>(x: T, y: T) -> (T, bool);
 
     /// Performs an exact division, resulting in undefined behavior where
@@ -1275,9 +1312,11 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
 
     /// Performs an unchecked left shift, resulting in undefined behavior when
     /// y < 0 or y >= N, where N is the width of T in bits.
+    #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shl<T>(x: T, y: T) -> T;
     /// Performs an unchecked right shift, resulting in undefined behavior when
     /// y < 0 or y >= N, where N is the width of T in bits.
+    #[rustc_const_stable(feature = "const_int_unchecked", since = "1.40.0")]
     pub fn unchecked_shr<T>(x: T, y: T) -> T;
 
     /// Returns the result of an unchecked addition, resulting in
@@ -1296,39 +1335,46 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_left` method. For example,
     /// [`std::u32::rotate_left`](../../std/primitive.u32.html#method.rotate_left)
+    #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
     pub fn rotate_left<T>(x: T, y: T) -> T;
 
     /// Performs rotate right.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `rotate_right` method. For example,
     /// [`std::u32::rotate_right`](../../std/primitive.u32.html#method.rotate_right)
+    #[rustc_const_stable(feature = "const_int_rotate", since = "1.40.0")]
     pub fn rotate_right<T>(x: T, y: T) -> T;
 
     /// Returns (a + b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_add` method. For example,
     /// [`std::u32::wrapping_add`](../../std/primitive.u32.html#method.wrapping_add)
+    #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_add<T>(a: T, b: T) -> T;
     /// Returns (a - b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_sub` method. For example,
     /// [`std::u32::wrapping_sub`](../../std/primitive.u32.html#method.wrapping_sub)
+    #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_sub<T>(a: T, b: T) -> T;
     /// Returns (a * b) mod 2<sup>N</sup>, where N is the width of T in bits.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `wrapping_mul` method. For example,
     /// [`std::u32::wrapping_mul`](../../std/primitive.u32.html#method.wrapping_mul)
+    #[rustc_const_stable(feature = "const_int_wrapping", since = "1.40.0")]
     pub fn wrapping_mul<T>(a: T, b: T) -> T;
 
     /// Computes `a + b`, while saturating at numeric bounds.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_add` method. For example,
     /// [`std::u32::saturating_add`](../../std/primitive.u32.html#method.saturating_add)
+    #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_add<T>(a: T, b: T) -> T;
     /// Computes `a - b`, while saturating at numeric bounds.
     /// The stabilized versions of this intrinsic are available on the integer
     /// primitives via the `saturating_sub` method. For example,
     /// [`std::u32::saturating_sub`](../../std/primitive.u32.html#method.saturating_sub)
+    #[rustc_const_stable(feature = "const_int_saturating", since = "1.40.0")]
     pub fn saturating_sub<T>(a: T, b: T) -> T;
 
     /// Returns the value of the discriminant for the variant in 'v',
@@ -1350,6 +1396,7 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
     pub fn nontemporal_store<T>(ptr: *mut T, val: T);
 
     /// See documentation of `<*const T>::offset_from` for details.
+    #[rustc_const_unstable(feature = "const_ptr_offset_from", issue = "none")]
     pub fn ptr_offset_from<T>(ptr: *const T, base: *const T) -> isize;
 
     /// Internal hook used by Miri to implement unwinding.
@@ -1376,11 +1423,7 @@ fn overlaps<T>(src: *const T, dst: *const T, count: usize) -> bool {
     let src_usize = src as usize;
     let dst_usize = dst as usize;
     let size = mem::size_of::<T>().checked_mul(count).unwrap();
-    let diff = if src_usize > dst_usize {
-        src_usize - dst_usize
-    } else {
-        dst_usize - src_usize
-    };
+    let diff = if src_usize > dst_usize { src_usize - dst_usize } else { dst_usize - src_usize };
     size > diff
 }