@@ -278,65 +278,74 @@ 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
- /// Bitcasts a value of one type to another. Both types must have the same
282
- /// size.
281
+ /// Reinterprets the bits of a value of one type as another type. Both types
282
+ /// must have the same size. Neither the original, nor the result, may be an
283
+ /// invalid value, or else you'll have UB on your hands.
283
284
///
284
285
/// `transmute::<T, U>(t)` is semantically equivalent to the following:
285
286
///
286
287
/// ```
288
+ /// // assuming that T and U are the same size
287
289
/// 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
290
+ /// let u: U = std::mem::uninitialized();
291
+ /// std::ptr::copy_nonoverlapping(&t as *const T as *const u8,
292
+ /// &mut u as *mut U as *mut u8,
293
+ /// std::mem::size_of::<T>());
294
+ /// std::mem::forget(t);
295
+ /// u
294
296
/// }
295
297
/// ```
296
298
///
297
- /// `transmute` is incredibly unsafe. There are an incredible number of ways
298
- /// to cause undefined behavior with this function. `transmute` should be
299
+ /// `transmute` is incredibly unsafe. There are a vast number of ways to
300
+ /// cause undefined behavior with this function. `transmute` should be
299
301
/// the absolute last resort.
300
302
///
301
303
/// The following is more complete documentation. Read it before using
302
304
/// `transmute`:
303
305
/// [nomicon](https://doc.rust-lang.org/nomicon/transmutes.html)
304
306
///
305
- /// # Examples
307
+ /// # Alternatives
308
+ ///
309
+ /// There are very few good cases for `transmute`. Most can be achieved
310
+ /// through other means. Some more or less common uses, and a better way,
311
+ /// are as follows:
306
312
///
307
313
/// ```
308
314
/// use std::mem;
309
315
///
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
- /// ```
316
+ /// // turning a pointer into a usize
317
+ /// let ptr = &0;
318
+ /// let ptr_num_transmute = std::mem::transmute::<&i32, usize>(ptr);
319
+ /// // now with more `as`
320
+ /// let ptr_num_cast = ptr as *const i32 as usize;
319
321
///
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
322
///
324
- /// ```
325
323
/// // Turning a *mut T into an &mut T
326
324
/// let ptr: *mut i32 = &mut 0;
327
- /// let reF_transmuted = std::mem::transmute::<*mut i32, &mut i32>(ptr);
325
+ /// let ref_transmuted = std::mem::transmute::<*mut i32, &mut i32>(ptr);
326
+ /// // Use reborrows
328
327
/// let ref_casted = &mut *ptr;
329
- /// ```
330
328
///
331
- /// ```
329
+ ///
332
330
/// // Turning an &mut T into an &mut U
333
331
/// let ptr = &mut 0;
334
332
/// 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
- /// ```
333
+ /// // Reborrowing continues to play a role here, but now we add `as` casts
334
+ /// let val_casts = &mut *(ptr as *mut i32 as *mut u32);
335
+ ///
336
+ ///
337
+ /// // Turning an `&str` into an `&[u8]`
338
+ /// let slice = unsafe { mem::transmute::<&str, &[u8]>("Rust") };
339
+ /// assert_eq!(slice, [82, 117, 115, 116]);
340
+ /// // this is not a good way to do this.
341
+ /// // use .as_bytes()
342
+ /// let slice = "Rust".as_bytes();
343
+ /// assert_eq!(slice, [82, 117, 115, 116]);
344
+ /// // Or, just use a byte string, if you have control over the string
345
+ /// // literal
346
+ /// assert_eq!(b"Rust", [82, 117, 116, 116]);
347
+ ///
338
348
///
339
- /// ```
340
349
/// // Copying an `&mut T` to reslice:
341
350
/// fn split_at_mut_transmute<T>(slice: &mut [T], index: usize)
342
351
/// -> (&mut [T], &mut [T]) {
@@ -345,7 +354,7 @@ extern "rust-intrinsic" {
345
354
/// let slice2 = std::mem::transmute::<&mut [T], &mut [T]>(slice);
346
355
/// (slice[0..index], slice2[index..len])
347
356
/// }
348
- /// // or:
357
+ /// // Again, use `as` and reborrowing
349
358
/// fn split_at_mut_casts<T>(slice: &mut [T], index: usize)
350
359
/// -> (&mut [T], &mut [T]) {
351
360
/// let len = slice.len();
@@ -355,12 +364,15 @@ extern "rust-intrinsic" {
355
364
/// }
356
365
/// ```
357
366
///
358
- /// There are valid uses of transmute.
367
+ /// # Examples
368
+ ///
369
+ /// There are valid uses of transmute, though they are few and far between.
359
370
///
360
371
/// ```
361
372
/// // getting the bitpattern of a floating point type
362
373
/// let x = std::mem::transmute::<f32, u32>(0.0/0.0)
363
374
///
375
+ ///
364
376
/// // turning a pointer into a function pointer
365
377
/// // in file.c: `int foo(void) { ... }`
366
378
/// let handle: *mut libc::c_void = libc::dlopen(
@@ -372,15 +384,14 @@ extern "rust-intrinsic" {
372
384
/// extern fn() -> libc::c_int>(foo);
373
385
/// println!("{}", foo());
374
386
///
387
+ ///
375
388
/// // extending an invariant lifetime; this is advanced, very unsafe rust
376
389
/// struct T<'a>(&'a i32);
377
390
/// let value = 0;
378
391
/// let t = T::new(&value);
379
392
/// let ptr = &mut t;
380
393
/// let ptr_extended = std::mem::transmute::<&mut T, &mut T<'static>>(ptr);
381
394
/// ```
382
- ///
383
- /// But these are few and far between.
384
395
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
385
396
pub fn transmute < T , U > ( e : T ) -> U ;
386
397
0 commit comments