@@ -277,17 +277,200 @@ extern "rust-intrinsic" {
277
277
/// Moves a value out of scope without running drop glue.
278
278
pub fn forget < T > ( _: T ) -> ( ) ;
279
279
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).
281
283
///
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.
283
295
///
284
296
/// # Examples
285
297
///
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
+ ///
286
303
/// ```
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`:
288
345
///
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
+ /// }
291
474
/// ```
292
475
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
293
476
pub fn transmute < T , U > ( e : T ) -> U ;
0 commit comments