@@ -278,18 +278,109 @@ extern "rust-intrinsic" {
278
278
/// Moves a value out of scope without running drop glue.
279
279
pub fn forget < T > ( _: T ) -> ( ) ;
280
280
281
- /// Unsafely transforms a value of one type into a value of another type.
281
+ /// Bitcasts a value of one type to another. Both types must have the same
282
+ /// size.
282
283
///
283
- /// Both types must have the same size.
284
+ /// `transmute::<T, U>(t)` is semantically equivalent to the following:
285
+ ///
286
+ /// ```
287
+ /// fn transmute<T, U>(t: T) -> U {
288
+ /// let u: U = std::mem::uninitialized();
289
+ /// std::ptr::copy_nonoverlapping(&t as *const T as *const u8,
290
+ /// &mut u as *mut U as *mut u8,
291
+ /// std::mem::size_of::<T>());
292
+ /// std::mem::forget(t);
293
+ /// u
294
+ /// }
295
+ /// ```
296
+ ///
297
+ /// `transmute` is incredibly unsafe. There are an incredible number of ways
298
+ /// to cause undefined behavior with this function. `transmute` should be
299
+ /// the absolute last resort.
300
+ ///
301
+ /// The following is more complete documentation. Read it before using
302
+ /// `transmute`:
303
+ /// [nomicon](https://doc.rust-lang.org/nomicon/transmutes.html)
284
304
///
285
305
/// # Examples
286
306
///
287
307
/// ```
288
308
/// use std::mem;
289
309
///
290
- /// let array: &[u8] = unsafe { mem::transmute("Rust") };
291
- /// assert_eq!(array, [82, 117, 115, 116]);
310
+ /// let slice: &[u8] = unsafe { mem::transmute::<&str, &[u8]>("Rust") };
311
+ /// assert_eq!(slice, [82, 117, 115, 116]);
312
+ /// // this is not a good way to do this.
313
+ /// // use .as_bytes()
314
+ /// let slice = "Rust".as_bytes();
315
+ /// assert_eq!(slice, [82, 117, 115, 116]);
316
+ /// // Or, just use a byte string
317
+ /// assert_eq!(b"Rust", [82, 117, 116, 116]);
318
+ /// ```
319
+ ///
320
+ /// There are very few good cases for `transmute`. Most can be achieved
321
+ /// through other means. Some commone uses, and the less unsafe way, are as
322
+ /// follows:
323
+ ///
324
+ /// ```
325
+ /// // Turning a *mut T into an &mut T
326
+ /// let ptr: *mut i32 = &mut 0;
327
+ /// let reF_transmuted = std::mem::transmute::<*mut i32, &mut i32>(ptr);
328
+ /// let ref_casted = &mut *ptr;
329
+ /// ```
330
+ ///
292
331
/// ```
332
+ /// // Turning an &mut T into an &mut U
333
+ /// let ptr = &mut 0;
334
+ /// let val_transmuted = std::mem::transmute::<&mut i32, &mut u32>(ptr);
335
+ /// // There is a better way, using `as` and reborrowing:
336
+ /// let val_casts = &mut *(ptr as *mut T as *mut U);
337
+ /// ```
338
+ ///
339
+ /// ```
340
+ /// // Copying an `&mut T` to reslice:
341
+ /// fn split_at_mut_transmute<T>(slice: &mut [T], index: usize)
342
+ /// -> (&mut [T], &mut [T]) {
343
+ /// let len = slice.len();
344
+ /// assert!(index < len);
345
+ /// let slice2 = std::mem::transmute::<&mut [T], &mut [T]>(slice);
346
+ /// (slice[0..index], slice2[index..len])
347
+ /// }
348
+ /// // or:
349
+ /// fn split_at_mut_casts<T>(slice: &mut [T], index: usize)
350
+ /// -> (&mut [T], &mut [T]) {
351
+ /// let len = slice.len();
352
+ /// assert!(index < len);
353
+ /// let slice2 = &mut *(slice as *mut [T]); // actually typesafe!
354
+ /// (slice[0..index], slice2[index..len])
355
+ /// }
356
+ /// ```
357
+ ///
358
+ /// There are valid uses of transmute.
359
+ ///
360
+ /// ```
361
+ /// // getting the bitpattern of a floating point type
362
+ /// let x = std::mem::transmute::<f32, u32>(0.0/0.0)
363
+ ///
364
+ /// // turning a pointer into a function pointer
365
+ /// // in file.c: `int foo(void) { ... }`
366
+ /// let handle: *mut libc::c_void = libc::dlopen(
367
+ /// b"file.so\0".as_ptr() as *const libc::c_char, libc::RTLD_LAZY);
368
+ /// let foo: *mut libc::c_void = libc::dlsym(
369
+ /// handle,
370
+ /// b"foo\0".as_ptr() as *const libc::c_char);
371
+ /// let foo = std::mem::transmute::<*mut libc::c_void,
372
+ /// extern fn() -> libc::c_int>(foo);
373
+ /// println!("{}", foo());
374
+ ///
375
+ /// // extending an invariant lifetime; this is advanced, very unsafe rust
376
+ /// struct T<'a>(&'a i32);
377
+ /// let value = 0;
378
+ /// let t = T::new(&value);
379
+ /// let ptr = &mut t;
380
+ /// let ptr_extended = std::mem::transmute::<&mut T, &mut T<'static>>(ptr);
381
+ /// ```
382
+ ///
383
+ /// But these are few and far between.
293
384
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
294
385
pub fn transmute < T , U > ( e : T ) -> U ;
295
386
0 commit comments