Skip to content

Commit 233b45f

Browse files
committed
Fix up some things which scott mentioned
1 parent 3d03f75 commit 233b45f

File tree

1 file changed

+46
-35
lines changed

1 file changed

+46
-35
lines changed

src/libcore/intrinsics.rs

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -278,65 +278,74 @@ extern "rust-intrinsic" {
278278
/// Moves a value out of scope without running drop glue.
279279
pub fn forget<T>(_: T) -> ();
280280

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.
283284
///
284285
/// `transmute::<T, U>(t)` is semantically equivalent to the following:
285286
///
286287
/// ```
288+
/// // assuming that T and U are the same size
287289
/// 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
294296
/// }
295297
/// ```
296298
///
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
299301
/// the absolute last resort.
300302
///
301303
/// The following is more complete documentation. Read it before using
302304
/// `transmute`:
303305
/// [nomicon](https://doc.rust-lang.org/nomicon/transmutes.html)
304306
///
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:
306312
///
307313
/// ```
308314
/// use std::mem;
309315
///
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;
319321
///
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:
323322
///
324-
/// ```
325323
/// // Turning a *mut T into an &mut T
326324
/// 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
328327
/// let ref_casted = &mut *ptr;
329-
/// ```
330328
///
331-
/// ```
329+
///
332330
/// // Turning an &mut T into an &mut U
333331
/// let ptr = &mut 0;
334332
/// 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+
///
338348
///
339-
/// ```
340349
/// // Copying an `&mut T` to reslice:
341350
/// fn split_at_mut_transmute<T>(slice: &mut [T], index: usize)
342351
/// -> (&mut [T], &mut [T]) {
@@ -345,7 +354,7 @@ extern "rust-intrinsic" {
345354
/// let slice2 = std::mem::transmute::<&mut [T], &mut [T]>(slice);
346355
/// (slice[0..index], slice2[index..len])
347356
/// }
348-
/// // or:
357+
/// // Again, use `as` and reborrowing
349358
/// fn split_at_mut_casts<T>(slice: &mut [T], index: usize)
350359
/// -> (&mut [T], &mut [T]) {
351360
/// let len = slice.len();
@@ -355,12 +364,15 @@ extern "rust-intrinsic" {
355364
/// }
356365
/// ```
357366
///
358-
/// There are valid uses of transmute.
367+
/// # Examples
368+
///
369+
/// There are valid uses of transmute, though they are few and far between.
359370
///
360371
/// ```
361372
/// // getting the bitpattern of a floating point type
362373
/// let x = std::mem::transmute::<f32, u32>(0.0/0.0)
363374
///
375+
///
364376
/// // turning a pointer into a function pointer
365377
/// // in file.c: `int foo(void) { ... }`
366378
/// let handle: *mut libc::c_void = libc::dlopen(
@@ -372,15 +384,14 @@ extern "rust-intrinsic" {
372384
/// extern fn() -> libc::c_int>(foo);
373385
/// println!("{}", foo());
374386
///
387+
///
375388
/// // extending an invariant lifetime; this is advanced, very unsafe rust
376389
/// struct T<'a>(&'a i32);
377390
/// let value = 0;
378391
/// let t = T::new(&value);
379392
/// let ptr = &mut t;
380393
/// let ptr_extended = std::mem::transmute::<&mut T, &mut T<'static>>(ptr);
381394
/// ```
382-
///
383-
/// But these are few and far between.
384395
#[stable(feature = "rust1", since = "1.0.0")]
385396
pub fn transmute<T, U>(e: T) -> U;
386397

0 commit comments

Comments
 (0)