@@ -277,17 +277,200 @@ extern "rust-intrinsic" {
277277 /// Moves a value out of scope without running drop glue.
278278 pub fn forget < T > ( _: T ) -> ( ) ;
279279
280- /// Unsafely transforms a value of one type into a value of another type.
280+ /// Reinterprets the bits of a value of one type as another type; both types
281+ /// must have the same size. Neither the original, nor the result, may be an
282+ /// [invalid value] (../../nomicon/meet-safe-and-unsafe.html).
281283 ///
282- /// Both types must have the same size.
284+ /// `transmute` is semantically equivalent to a bitwise move of one type
285+ /// into another. It copies the bits from the destination type into the
286+ /// source type, then forgets the original. It's equivalent to C's `memcpy`
287+ /// under the hood, just like `transmute_copy`.
288+ ///
289+ /// `transmute` is incredibly unsafe. There are a vast number of ways to
290+ /// cause undefined behavior with this function. `transmute` should be
291+ /// the absolute last resort.
292+ ///
293+ /// The [nomicon](../../nomicon/transmutes.html) has additional
294+ /// documentation.
283295 ///
284296 /// # Examples
285297 ///
298+ /// There are a few things that `transmute` is really useful for.
299+ ///
300+ /// Getting the bitpattern of a floating point type (or, more generally,
301+ /// type punning, when `T` and `U` aren't pointers):
302+ ///
286303 /// ```
287- /// use std::mem;
304+ /// let bitpattern = unsafe {
305+ /// std::mem::transmute::<f32, u32>(1.0)
306+ /// };
307+ /// assert_eq!(bitpattern, 0x3F800000);
308+ /// ```
309+ ///
310+ /// Turning a pointer into a function pointer:
311+ ///
312+ /// ```
313+ /// fn foo() -> i32 {
314+ /// 0
315+ /// }
316+ /// let pointer = foo as *const ();
317+ /// let function = unsafe {
318+ /// std::mem::transmute::<*const (), fn() -> i32>(pointer)
319+ /// };
320+ /// assert_eq!(function(), 0);
321+ /// ```
322+ ///
323+ /// Extending a lifetime, or shortening an invariant lifetime; this is
324+ /// advanced, very unsafe rust:
325+ ///
326+ /// ```
327+ /// struct R<'a>(&'a i32);
328+ /// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
329+ /// std::mem::transmute::<R<'b>, R<'static>>(r)
330+ /// }
331+ ///
332+ /// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
333+ /// -> &'b mut R<'c> {
334+ /// std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
335+ /// }
336+ /// ```
337+ ///
338+ /// # Alternatives
339+ ///
340+ /// However, many uses of `transmute` can be achieved through other means.
341+ /// `transmute` can transform any type into any other, with just the caveat
342+ /// that they're the same size, and often interesting results occur. Below
343+ /// are common applications of `transmute` which can be replaced with safe
344+ /// applications of `as`:
288345 ///
289- /// let array: &[u8] = unsafe { mem::transmute("Rust") };
290- /// assert_eq!(array, [82, 117, 115, 116]);
346+ /// Turning a pointer into a `usize`:
347+ ///
348+ /// ```
349+ /// let ptr = &0;
350+ /// let ptr_num_transmute = unsafe {
351+ /// std::mem::transmute::<&i32, usize>(ptr)
352+ /// };
353+ /// // Use an `as` cast instead
354+ /// let ptr_num_cast = ptr as *const i32 as usize;
355+ /// ```
356+ ///
357+ /// Turning a `*mut T` into an `&mut T`:
358+ ///
359+ /// ```
360+ /// let ptr: *mut i32 = &mut 0;
361+ /// let ref_transmuted = unsafe {
362+ /// std::mem::transmute::<*mut i32, &mut i32>(ptr)
363+ /// };
364+ /// // Use a reborrow instead
365+ /// let ref_casted = unsafe { &mut *ptr };
366+ /// ```
367+ ///
368+ /// Turning an `&mut T` into an `&mut U`:
369+ ///
370+ /// ```
371+ /// let ptr = &mut 0;
372+ /// let val_transmuted = unsafe {
373+ /// std::mem::transmute::<&mut i32, &mut u32>(ptr)
374+ /// };
375+ /// // Now, put together `as` and reborrowing - note the chaining of `as`
376+ /// // `as` is not transitive
377+ /// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
378+ /// ```
379+ ///
380+ /// Turning an `&str` into an `&[u8]`:
381+ ///
382+ /// ```
383+ /// // this is not a good way to do this.
384+ /// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
385+ /// assert_eq!(slice, &[82, 117, 115, 116]);
386+ /// // You could use `str::as_bytes`
387+ /// let slice = "Rust".as_bytes();
388+ /// assert_eq!(slice, &[82, 117, 115, 116]);
389+ /// // Or, just use a byte string, if you have control over the string
390+ /// // literal
391+ /// assert_eq!(b"Rust", &[82, 117, 115, 116]);
392+ /// ```
393+ ///
394+ /// Turning a `Vec<&T>` into a `Vec<Option<&T>>`:
395+ ///
396+ /// ```
397+ /// let store = [0, 1, 2, 3];
398+ /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
399+ /// // Using transmute: this is Undefined Behavior, and a bad idea.
400+ /// // However, it is no-copy.
401+ /// let v_transmuted = unsafe {
402+ /// std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
403+ /// v_orig.clone())
404+ /// };
405+ /// // This is the suggested, safe way.
406+ /// // It does copy the entire Vector, though, into a new array.
407+ /// let v_collected = v_orig.clone()
408+ /// .into_iter()
409+ /// .map(|r| Some(r))
410+ /// .collect::<Vec<Option<&i32>>>();
411+ /// // The no-copy, unsafe way, still using transmute, but not UB.
412+ /// // This is equivalent to the original, but safer, and reuses the
413+ /// // same Vec internals. Therefore the new inner type must have the
414+ /// // exact same size, and the same or lesser alignment, as the old
415+ /// // type. The same caveats exist for this method as transmute, for
416+ /// // the original inner type (`&i32`) to the converted inner type
417+ /// // (`Option<&i32>`), so read the nomicon pages linked above.
418+ /// let v_from_raw = unsafe {
419+ /// Vec::from_raw_parts(v_orig.as_mut_ptr(),
420+ /// v_orig.len(),
421+ /// v_orig.capacity())
422+ /// };
423+ /// std::mem::forget(v_orig);
424+ /// ```
425+ ///
426+ /// Implementing `split_at_mut`:
427+ ///
428+ /// ```
429+ /// use std::{slice, mem};
430+ /// // There are multiple ways to do this; and there are multiple problems
431+ /// // with the following, transmute, way.
432+ /// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
433+ /// -> (&mut [T], &mut [T]) {
434+ /// let len = slice.len();
435+ /// assert!(mid <= len);
436+ /// unsafe {
437+ /// let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
438+ /// // first: transmute is not typesafe; all it checks is that T and
439+ /// // U are of the same size. Second, right here, you have two
440+ /// // mutable references pointing to the same memory.
441+ /// (&mut slice[0..mid], &mut slice2[mid..len])
442+ /// }
443+ /// }
444+ /// // This gets rid of the typesafety problems; `&mut *` will *only* give
445+ /// // you an `&mut T` from an `&mut T` or `*mut T`.
446+ /// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
447+ /// -> (&mut [T], &mut [T]) {
448+ /// let len = slice.len();
449+ /// assert!(mid <= len);
450+ /// unsafe {
451+ /// let slice2 = &mut *(slice as *mut [T]);
452+ /// // however, you still have two mutable references pointing to
453+ /// // the same memory.
454+ /// (&mut slice[0..mid], &mut slice2[mid..len])
455+ /// }
456+ /// }
457+ /// // This is how the standard library does it. This is the best method, if
458+ /// // you need to do something like this
459+ /// fn split_at_stdlib<T>(slice: &mut [T], mid: usize)
460+ /// -> (&mut [T], &mut [T]) {
461+ /// let len = slice.len();
462+ /// assert!(mid <= len);
463+ /// unsafe {
464+ /// let ptr = slice.as_mut_ptr();
465+ /// // This now has three mutable references pointing at the same
466+ /// // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
467+ /// // `slice` is never used after `let ptr = ...`, and so one can
468+ /// // treat it as "dead", and therefore, you only have two real
469+ /// // mutable slices.
470+ /// (slice::from_raw_parts_mut(ptr, mid),
471+ /// slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
472+ /// }
473+ /// }
291474 /// ```
292475 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
293476 pub fn transmute < T , U > ( e : T ) -> U ;
0 commit comments