]> git.proxmox.com Git - rustc.git/blobdiff - src/libcore/intrinsics.rs
New upstream version 1.14.0+dfsg1
[rustc.git] / src / libcore / intrinsics.rs
index 03bcf9caeea0cab30ad450440deb2ffc271acc27..e844a158484af488b2adea942de2127bc12644cc 100644 (file)
@@ -10,7 +10,7 @@
 
 //! rustc compiler intrinsics.
 //!
-//! The corresponding definitions are in librustc_trans/trans/intrinsic.rs.
+//! The corresponding definitions are in librustc_trans/intrinsic.rs.
 //!
 //! # Volatiles
 //!
             issue = "0")]
 #![allow(missing_docs)]
 
-use marker::Sized;
-
 extern "rust-intrinsic" {
 
     // NB: These intrinsics take raw pointers because they mutate aliased
     // memory, which is not valid for either `&` or `&mut`.
 
-    #[cfg(all(stage0, not(cargobuild)))]
-    pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> T;
-    #[cfg(all(stage0, not(cargobuild)))]
-    pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> T;
-    #[cfg(all(stage0, not(cargobuild)))]
-    pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> T;
-    #[cfg(all(stage0, not(cargobuild)))]
-    pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> T;
-    #[cfg(all(stage0, not(cargobuild)))]
-    pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> T;
-
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg_acq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg_rel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg_acqrel<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg_relaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg_failacq<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg_acq_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
-    #[cfg(any(not(stage0), cargobuild))]
     pub fn atomic_cxchg_acqrel_failrelaxed<T>(dst: *mut T, old: T, src: T) -> (T, bool);
 
     pub fn atomic_cxchgweak<T>(dst: *mut T, old: T, src: T) -> (T, bool);
@@ -188,6 +166,15 @@ extern "rust-intrinsic" {
     pub fn atomic_singlethreadfence_rel();
     pub fn atomic_singlethreadfence_acqrel();
 
+    /// Magic intrinsic that derives its meaning from attributes
+    /// attached to the function.
+    ///
+    /// For example, dataflow uses this to inject static assertions so
+    /// that `rustc_peek(potentially_uninitialized)` would actually
+    /// double-check that dataflow did indeed compute that it is
+    /// uninitialized at that point in the control flow.
+    pub fn rustc_peek<T>(_: T) -> T;
+
     /// Aborts the execution of the process.
     pub fn abort() -> !;
 
@@ -207,16 +194,25 @@ extern "rust-intrinsic" {
     /// own, or if it does not enable any significant optimizations.
     pub fn assume(b: bool);
 
+    /// Hints to the compiler that branch condition is likely to be true.
+    /// Returns the value passed to it.
+    ///
+    /// Any use other than with `if` statements will probably not have an effect.
+    pub fn likely(b: bool) -> bool;
+
+    /// Hints to the compiler that branch condition is likely to be false.
+    /// Returns the value passed to it.
+    ///
+    /// Any use other than with `if` statements will probably not have an effect.
+    pub fn unlikely(b: bool) -> bool;
+
     /// Executes a breakpoint trap, for inspection by a debugger.
     pub fn breakpoint();
 
     /// The size of a type in bytes.
     ///
-    /// This is the exact number of bytes in memory taken up by a
-    /// value of the given type. In other words, a memset of this size
-    /// would *exactly* overwrite a value. When laid out in vectors
-    /// and structures there may be additional padding between
-    /// elements.
+    /// More specifically, this is the offset in bytes between successive
+    /// items of the same type, including alignment padding.
     pub fn size_of<T>() -> usize;
 
     /// Moves a value to an uninitialized memory location.
@@ -258,19 +254,6 @@ extern "rust-intrinsic" {
     /// crate it is invoked in.
     pub fn type_id<T: ?Sized + 'static>() -> u64;
 
-    /// Creates a value initialized to so that its drop flag,
-    /// if any, says that it has been dropped.
-    ///
-    /// `init_dropped` is unsafe because it returns a datum with all
-    /// of its bytes set to the drop flag, which generally does not
-    /// correspond to a valid value.
-    ///
-    /// This intrinsic is likely to be deprecated in the future when
-    /// Rust moves to non-zeroing dynamic drop (and thus removes the
-    /// embedded drop flags that are being established by this
-    /// intrinsic).
-    pub fn init_dropped<T>() -> T;
-
     /// Creates a value initialized to zero.
     ///
     /// `init` is unsafe because it returns a zeroed-out datum,
@@ -291,27 +274,217 @@ extern "rust-intrinsic" {
     /// Moves a value out of scope without running drop glue.
     pub fn forget<T>(_: T) -> ();
 
-    /// Unsafely transforms a value of one type into a value of another type.
+    /// Reinterprets the bits of a value of one type as another type.
     ///
-    /// Both types must have the same size.
+    /// Both types must have the same size. Neither the original, nor the result,
+    /// may be an [invalid value](../../nomicon/meet-safe-and-unsafe.html).
+    ///
+    /// `transmute` is semantically equivalent to a bitwise move of one type
+    /// into another. It copies the bits from the source value into the
+    /// destination value, then forgets the original. It's equivalent to C's
+    /// `memcpy` under the hood, just like `transmute_copy`.
+    ///
+    /// `transmute` is **incredibly** unsafe. There are a vast number of ways to
+    /// cause [undefined behavior][ub] with this function. `transmute` should be
+    /// the absolute last resort.
+    ///
+    /// The [nomicon](../../nomicon/transmutes.html) has additional
+    /// documentation.
+    ///
+    /// [ub]: ../../reference.html#behavior-considered-undefined
     ///
     /// # Examples
     ///
+    /// There are a few things that `transmute` is really useful for.
+    ///
+    /// Getting the bitpattern of a floating point type (or, more generally,
+    /// type punning, when `T` and `U` aren't pointers):
+    ///
     /// ```
-    /// use std::mem;
+    /// let bitpattern = unsafe {
+    ///     std::mem::transmute::<f32, u32>(1.0)
+    /// };
+    /// assert_eq!(bitpattern, 0x3F800000);
+    /// ```
+    ///
+    /// Turning a pointer into a function pointer. This is *not* portable to
+    /// machines where function pointers and data pointers have different sizes.
+    ///
+    /// ```
+    /// fn foo() -> i32 {
+    ///     0
+    /// }
+    /// let pointer = foo as *const ();
+    /// let function = unsafe {
+    ///     std::mem::transmute::<*const (), fn() -> i32>(pointer)
+    /// };
+    /// assert_eq!(function(), 0);
+    /// ```
+    ///
+    /// Extending a lifetime, or shortening an invariant lifetime. This is
+    /// advanced, very unsafe Rust!
+    ///
+    /// ```
+    /// struct R<'a>(&'a i32);
+    /// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
+    ///     std::mem::transmute::<R<'b>, R<'static>>(r)
+    /// }
+    ///
+    /// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
+    ///                                              -> &'b mut R<'c> {
+    ///     std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
+    /// }
+    /// ```
+    ///
+    /// # Alternatives
+    ///
+    /// Don't despair: many uses of `transmute` can be achieved through other means.
+    /// Below are common applications of `transmute` which can be replaced with safer
+    /// constructs.
+    ///
+    /// Turning a pointer into a `usize`:
+    ///
+    /// ```
+    /// let ptr = &0;
+    /// let ptr_num_transmute = unsafe {
+    ///     std::mem::transmute::<&i32, usize>(ptr)
+    /// };
+    ///
+    /// // Use an `as` cast instead
+    /// let ptr_num_cast = ptr as *const i32 as usize;
+    /// ```
+    ///
+    /// Turning a `*mut T` into an `&mut T`:
+    ///
+    /// ```
+    /// let ptr: *mut i32 = &mut 0;
+    /// let ref_transmuted = unsafe {
+    ///     std::mem::transmute::<*mut i32, &mut i32>(ptr)
+    /// };
     ///
-    /// let array: &[u8] = unsafe { mem::transmute("Rust") };
-    /// assert_eq!(array, [82, 117, 115, 116]);
+    /// // Use a reborrow instead
+    /// let ref_casted = unsafe { &mut *ptr };
+    /// ```
+    ///
+    /// Turning an `&mut T` into an `&mut U`:
+    ///
+    /// ```
+    /// let ptr = &mut 0;
+    /// let val_transmuted = unsafe {
+    ///     std::mem::transmute::<&mut i32, &mut u32>(ptr)
+    /// };
+    ///
+    /// // Now, put together `as` and reborrowing - note the chaining of `as`
+    /// // `as` is not transitive
+    /// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
+    /// ```
+    ///
+    /// Turning an `&str` into an `&[u8]`:
+    ///
+    /// ```
+    /// // this is not a good way to do this.
+    /// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
+    /// assert_eq!(slice, &[82, 117, 115, 116]);
+    ///
+    /// // You could use `str::as_bytes`
+    /// let slice = "Rust".as_bytes();
+    /// assert_eq!(slice, &[82, 117, 115, 116]);
+    ///
+    /// // Or, just use a byte string, if you have control over the string
+    /// // literal
+    /// assert_eq!(b"Rust", &[82, 117, 115, 116]);
+    /// ```
+    ///
+    /// Turning a `Vec<&T>` into a `Vec<Option<&T>>`:
+    ///
+    /// ```
+    /// let store = [0, 1, 2, 3];
+    /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
+    ///
+    /// // Using transmute: this is Undefined Behavior, and a bad idea.
+    /// // However, it is no-copy.
+    /// let v_transmuted = unsafe {
+    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
+    ///         v_orig.clone())
+    /// };
+    ///
+    /// // This is the suggested, safe way.
+    /// // It does copy the entire vector, though, into a new array.
+    /// let v_collected = v_orig.clone()
+    ///                         .into_iter()
+    ///                         .map(|r| Some(r))
+    ///                         .collect::<Vec<Option<&i32>>>();
+    ///
+    /// // The no-copy, unsafe way, still using transmute, but not UB.
+    /// // This is equivalent to the original, but safer, and reuses the
+    /// // same Vec internals. Therefore the new inner type must have the
+    /// // exact same size, and the same or lesser alignment, as the old
+    /// // type. The same caveats exist for this method as transmute, for
+    /// // the original inner type (`&i32`) to the converted inner type
+    /// // (`Option<&i32>`), so read the nomicon pages linked above.
+    /// let v_from_raw = unsafe {
+    ///     Vec::from_raw_parts(v_orig.as_mut_ptr(),
+    ///                         v_orig.len(),
+    ///                         v_orig.capacity())
+    /// };
+    /// std::mem::forget(v_orig);
+    /// ```
+    ///
+    /// Implementing `split_at_mut`:
+    ///
+    /// ```
+    /// use std::{slice, mem};
+    ///
+    /// // There are multiple ways to do this; and there are multiple problems
+    /// // with the following, transmute, way.
+    /// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
+    ///                              -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
+    ///         // first: transmute is not typesafe; all it checks is that T and
+    ///         // U are of the same size. Second, right here, you have two
+    ///         // mutable references pointing to the same memory.
+    ///         (&mut slice[0..mid], &mut slice2[mid..len])
+    ///     }
+    /// }
+    ///
+    /// // This gets rid of the typesafety problems; `&mut *` will *only* give
+    /// // you an `&mut T` from an `&mut T` or `*mut T`.
+    /// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
+    ///                          -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let slice2 = &mut *(slice as *mut [T]);
+    ///         // however, you still have two mutable references pointing to
+    ///         // the same memory.
+    ///         (&mut slice[0..mid], &mut slice2[mid..len])
+    ///     }
+    /// }
+    ///
+    /// // This is how the standard library does it. This is the best method, if
+    /// // you need to do something like this
+    /// fn split_at_stdlib<T>(slice: &mut [T], mid: usize)
+    ///                       -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let ptr = slice.as_mut_ptr();
+    ///         // This now has three mutable references pointing at the same
+    ///         // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
+    ///         // `slice` is never used after `let ptr = ...`, and so one can
+    ///         // treat it as "dead", and therefore, you only have two real
+    ///         // mutable slices.
+    ///         (slice::from_raw_parts_mut(ptr, mid),
+    ///          slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
+    ///     }
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn transmute<T, U>(e: T) -> U;
 
-    /// Gives the address for the return value of the enclosing function.
-    ///
-    /// Using this intrinsic in a function that does not use an out pointer
-    /// will trigger a compiler error.
-    pub fn return_address() -> *const u8;
-
     /// Returns `true` if the actual type given as `T` requires drop
     /// glue; returns `false` if the actual type provided for `T`
     /// implements `Copy`.
@@ -421,6 +594,19 @@ extern "rust-intrinsic" {
 
     /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
     /// bytes of memory starting at `dst` to `val`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::ptr;
+    ///
+    /// let mut vec = vec![0; 4];
+    /// unsafe {
+    ///     let vec_ptr = vec.as_mut_ptr();
+    ///     ptr::write_bytes(vec_ptr, b'a', 2);
+    /// }
+    /// assert_eq!(vec, [b'a', b'a', 0, 0]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize);
 
@@ -548,27 +734,22 @@ extern "rust-intrinsic" {
 
     /// Float addition that allows optimizations based on algebraic rules.
     /// May assume inputs are finite.
-    #[cfg(not(stage0))]
     pub fn fadd_fast<T>(a: T, b: T) -> T;
 
     /// Float subtraction that allows optimizations based on algebraic rules.
     /// May assume inputs are finite.
-    #[cfg(not(stage0))]
     pub fn fsub_fast<T>(a: T, b: T) -> T;
 
     /// Float multiplication that allows optimizations based on algebraic rules.
     /// May assume inputs are finite.
-    #[cfg(not(stage0))]
     pub fn fmul_fast<T>(a: T, b: T) -> T;
 
     /// Float division that allows optimizations based on algebraic rules.
     /// May assume inputs are finite.
-    #[cfg(not(stage0))]
     pub fn fdiv_fast<T>(a: T, b: T) -> T;
 
     /// Float remainder that allows optimizations based on algebraic rules.
     /// May assume inputs are finite.
-    #[cfg(not(stage0))]
     pub fn frem_fast<T>(a: T, b: T) -> T;