Skip to content

Commit

Permalink
Make sure the documentation compiles
Browse files Browse the repository at this point in the history
  • Loading branch information
ubsan committed Jul 3, 2016
1 parent 377bbfe commit 9e94ebf
Showing 1 changed file with 92 additions and 77 deletions.
169 changes: 92 additions & 77 deletions src/libcore/intrinsics.rs
Expand Up @@ -287,12 +287,12 @@ extern "rust-intrinsic" {
///
/// ```
/// // assuming that T and U are the same size
/// fn transmute<T, U>(t: T) -> U {
/// let u: U = std::mem::uninitialized();
/// unsafe fn transmute<T, U>(t: T) -> U {
/// let u: U = mem::uninitialized();
/// std::ptr::copy_nonoverlapping(&t as *const T as *const u8,
/// &mut u as *mut U as *mut u8,
/// std::mem::size_of::<T>());
/// std::mem::forget(t);
/// mem::size_of::<T>());
/// mem::forget(t);
/// u
/// }
/// ```
Expand All @@ -314,76 +314,85 @@ extern "rust-intrinsic" {
/// use std::mem;
///
/// // turning a pointer into a usize
/// let ptr = &0;
/// let ptr_num_transmute = std::mem::transmute::<&i32, usize>(ptr);
/// // Use `as` casts instead
/// let ptr_num_cast = ptr as *const i32 as usize;
///
/// {
/// let ptr = &0;
/// let ptr_num_transmute = mem::transmute::<&i32, usize>(ptr);
/// // Use `as` casts 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 = std::mem::transmute::<*mut i32, &mut i32>(ptr);
/// // Use reborrows
/// let ref_casted = &mut *ptr;
///
/// {
/// let ptr: *mut i32 = &mut 0;
/// let ref_transmuted = mem::transmute::<*mut i32, &mut i32>(ptr);
/// // Use reborrows
/// let ref_casted = &mut *ptr;
/// }
///
/// // Turning an &mut T into an &mut U
/// let ptr = &mut 0;
/// let val_transmuted = std::mem::transmute::<&mut i32, &mut u32>(ptr);
/// // Now let's put together `as` and reborrowing
/// let val_casts = &mut *(ptr as *mut i32 as *mut u32);
///
/// {
/// let ptr = &mut 0;
/// let val_transmuted = mem::transmute::<&mut i32, &mut u32>(ptr);
/// // Now let's put together `as` and reborrowing
/// let val_casts = &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 { 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, 116, 116]);
///
/// {
/// // this is not a good way to do this.
/// let slice = unsafe { 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, 116, 116]);
/// }
///
/// // Turning a Vec<&T> into a Vec<Option<&T>>
/// let store = [0, 1, 2, 3];
/// let v_orig = store.iter().collect::<Vec<&i32>>();
/// // Using transmute; Undefined Behavior
/// let v_transmuted = mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
/// v_orig);
/// // The suggested, safe way
/// let v_collected = v_orig.into_iter()
/// .map(|r| Some(r))
/// .collect::<Vec<Option<&i32>>>();
/// // The no-copy, unsafe way, still using transmute, but not UB
/// let v_no_copy = Vec::from_raw_parts(v_orig.as_mut_ptr(),
/// v_orig.len(),
/// v_orig.capacity());
/// mem::forget(v_orig);
/// // 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 page linked above.
/// {
/// let store = [0, 1, 2, 3];
/// let v_orig = store.iter().collect::<Vec<&i32>>();
/// // Using transmute; Undefined Behavior
/// let v_transmuted = mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
/// v_orig.clone());
/// // The suggested, safe way
/// 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 page linked above.
/// let v_no_copy = Vec::from_raw_parts(v_orig.as_mut_ptr(),
/// v_orig.len(),
/// v_orig.capacity());
/// mem::forget(v_orig);
/// }
///
///
/// // Copying an `&mut T` to reslice:
/// fn split_at_mut_transmute<T>(slice: &mut [T], index: usize)
/// {
/// fn split_at_mut_transmute<T>(slice: &mut [T], index: usize)
/// -> (&mut [T], &mut [T]) {
/// let len = slice.len();
/// assert!(index < len);
/// let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
/// (slice[0..index], slice2[index..len])
/// }
/// // Again, use `as` and reborrowing
/// fn split_at_mut_casts<T>(slice: &mut [T], index: usize)
/// -> (&mut [T], &mut [T]) {
/// let len = slice.len();
/// assert!(index < len);
/// let slice2 = std::mem::transmute::<&mut [T], &mut [T]>(slice);
/// (slice[0..index], slice2[index..len])
/// }
/// // Again, use `as` and reborrowing
/// fn split_at_mut_casts<T>(slice: &mut [T], index: usize)
/// -> (&mut [T], &mut [T]) {
/// let len = slice.len();
/// assert!(index < len);
/// let slice2 = &mut *(slice as *mut [T]); // actually typesafe!
/// (slice[0..index], slice2[index..len])
/// let len = slice.len();
/// assert!(index < len);
/// let slice2 = &mut *(slice as *mut [T]); // actually typesafe!
/// (slice[0..index], slice2[index..len])
/// }
/// }
/// ```
///
Expand All @@ -393,27 +402,33 @@ extern "rust-intrinsic" {
///
/// ```
/// // getting the bitpattern of a floating point type
/// let x = std::mem::transmute::<f32, u32>(0.0/0.0)
/// {
/// let x = mem::transmute::<f32, u32>(0.0/0.0)
/// }
///
///
/// // turning a pointer into a function pointer
/// // in file.c: `int foo(void) { ... }`
/// let handle: *mut libc::c_void = libc::dlopen(
/// b"file.so\0".as_ptr() as *const libc::c_char, libc::RTLD_LAZY);
/// let foo: *mut libc::c_void = libc::dlsym(
/// handle,
/// b"foo\0".as_ptr() as *const libc::c_char);
/// let foo = std::mem::transmute::<*mut libc::c_void,
/// extern fn() -> libc::c_int>(foo);
/// println!("{}", foo());
/// {
/// // in file.c: `int foo(void) { ... }`
/// let handle: *mut libc::c_void = libc::dlopen(
/// b"file.so\0".as_ptr() as *const libc::c_char, libc::RTLD_LAZY);
/// let foo: *mut libc::c_void = libc::dlsym(
/// handle,
/// b"foo\0".as_ptr() as *const libc::c_char);
/// let foo = mem::transmute::<*mut libc::c_void,
/// extern fn() -> libc::c_int>(foo);
/// println!("{}", foo());
/// }
///
///
/// // extending an invariant lifetime; this is advanced, very unsafe rust
/// struct T<'a>(&'a i32);
/// let value = 0;
/// let t = T::new(&value);
/// let ptr = &mut t;
/// let ptr_extended = std::mem::transmute::<&mut T, &mut T<'static>>(ptr);
/// {
/// struct T<'a>(&'a i32);
/// let value = 0;
/// let t = T::new(&value);
/// let ptr = &mut t;
/// let ptr_extended = mem::transmute::<&mut T, &mut T<'static>>(ptr);
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn transmute<T, U>(e: T) -> U;
Expand Down

0 comments on commit 9e94ebf

Please sign in to comment.