Skip to content

Commit 7ec44e6

Browse files
committed
Fix tests
1 parent 9e94ebf commit 7ec44e6

File tree

1 file changed

+138
-100
lines changed

1 file changed

+138
-100
lines changed

src/libcore/intrinsics.rs

Lines changed: 138 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,13 @@ extern "rust-intrinsic" {
286286
/// `transmute::<T, U>(t)` is semantically equivalent to the following:
287287
///
288288
/// ```
289+
/// use std::{mem, ptr};
289290
/// // assuming that T and U are the same size
290291
/// unsafe fn transmute<T, U>(t: T) -> U {
291-
/// let u: U = mem::uninitialized();
292-
/// std::ptr::copy_nonoverlapping(&t as *const T as *const u8,
293-
/// &mut u as *mut U as *mut u8,
294-
/// mem::size_of::<T>());
292+
/// let mut u: U = mem::uninitialized();
293+
/// ptr::copy_nonoverlapping(&t as *const T as *const u8,
294+
/// &mut u as *mut U as *mut u8,
295+
/// mem::size_of::<T>());
295296
/// mem::forget(t);
296297
/// u
297298
/// }
@@ -310,88 +311,115 @@ extern "rust-intrinsic" {
310311
/// through other means. Some more or less common uses, and a better way,
311312
/// are as follows:
312313
///
314+
/// Turning a pointer into a `usize`:
315+
/// ```
316+
/// let ptr = &0;
317+
/// let ptr_num_transmute = mem::transmute::<&i32, usize>(ptr);
318+
/// // Use `as` casts instead
319+
/// let ptr_num_cast = ptr as *const i32 as usize;
313320
/// ```
314-
/// use std::mem;
315-
///
316-
/// // turning a pointer into a usize
317-
/// {
318-
/// let ptr = &0;
319-
/// let ptr_num_transmute = mem::transmute::<&i32, usize>(ptr);
320-
/// // Use `as` casts instead
321-
/// let ptr_num_cast = ptr as *const i32 as usize;
322-
/// }
323-
///
324-
/// // Turning a *mut T into an &mut T
325-
/// {
326-
/// let ptr: *mut i32 = &mut 0;
327-
/// let ref_transmuted = mem::transmute::<*mut i32, &mut i32>(ptr);
328-
/// // Use reborrows
329-
/// let ref_casted = &mut *ptr;
330-
/// }
331321
///
332-
/// // Turning an &mut T into an &mut U
333-
/// {
334-
/// let ptr = &mut 0;
335-
/// let val_transmuted = mem::transmute::<&mut i32, &mut u32>(ptr);
336-
/// // Now let's put together `as` and reborrowing
337-
/// let val_casts = &mut *(ptr as *mut i32 as *mut u32);
338-
/// }
322+
/// Turning a `*mut T` into an `&mut T`:
323+
/// ```
324+
/// let ptr: *mut i32 = &mut 0;
325+
/// let ref_transmuted = mem::transmute::<*mut i32, &mut i32>(ptr);
326+
/// // Use reborrows
327+
/// let ref_casted = &mut *ptr;
328+
/// ```
339329
///
340-
/// // Turning an `&str` into an `&[u8]`
341-
/// {
342-
/// // this is not a good way to do this.
343-
/// let slice = unsafe { mem::transmute::<&str, &[u8]>("Rust") };
344-
/// assert_eq!(slice, [82, 117, 115, 116]);
345-
/// // You could use `str::as_bytes`
346-
/// let slice = "Rust".as_bytes();
347-
/// assert_eq!(slice, [82, 117, 115, 116]);
348-
/// // Or, just use a byte string, if you have control over the string
349-
/// // literal
350-
/// assert_eq!(b"Rust", [82, 117, 116, 116]);
351-
/// }
330+
/// Turning an `&mut T` into an `&mut U`:
331+
/// ```
332+
/// let ptr = &mut 0;
333+
/// let val_transmuted = mem::transmute::<&mut i32, &mut u32>(ptr);
334+
/// // Now let's put together `as` and reborrowing
335+
/// let val_casts = &mut *(ptr as *mut i32 as *mut u32);
336+
/// ```
352337
///
353-
/// // Turning a Vec<&T> into a Vec<Option<&T>>
354-
/// {
355-
/// let store = [0, 1, 2, 3];
356-
/// let v_orig = store.iter().collect::<Vec<&i32>>();
357-
/// // Using transmute; Undefined Behavior
358-
/// let v_transmuted = mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
359-
/// v_orig.clone());
360-
/// // The suggested, safe way
361-
/// let v_collected = v_orig.clone()
362-
/// .into_iter()
363-
/// .map(|r| Some(r))
364-
/// .collect::<Vec<Option<&i32>>>();
365-
/// // The no-copy, unsafe way, still using transmute, but not UB
366-
/// // This is equivalent to the original, but safer, and reuses the
367-
/// // same Vec internals. Therefore the new inner type must have the
368-
/// // exact same size, and the same or lesser alignment, as the old
369-
/// // type. The same caveats exist for this method as transmute, for
370-
/// // the original inner type (`&i32`) to the converted inner type
371-
/// // (`Option<&i32>`), so read the nomicon page linked above.
372-
/// let v_no_copy = Vec::from_raw_parts(v_orig.as_mut_ptr(),
373-
/// v_orig.len(),
374-
/// v_orig.capacity());
375-
/// mem::forget(v_orig);
376-
/// }
338+
/// Turning an `&str` into an `&[u8]`:
339+
/// ```
340+
/// // this is not a good way to do this.
341+
/// let slice = unsafe { mem::transmute::<&str, &[u8]>("Rust") };
342+
/// assert_eq!(slice, [82, 117, 115, 116]);
343+
/// // You could use `str::as_bytes`
344+
/// let slice = "Rust".as_bytes();
345+
/// assert_eq!(slice, [82, 117, 115, 116]);
346+
/// // Or, just use a byte string, if you have control over the string
347+
/// // literal
348+
/// assert_eq!(b"Rust", [82, 117, 116, 116]);
349+
/// ```
377350
///
351+
/// Turning a `Vec<&T>` into a `Vec<Option<&T>>`:
352+
/// ```
353+
/// let store = [0, 1, 2, 3];
354+
/// let v_orig = store.iter().collect::<Vec<&i32>>();
355+
/// // Using transmute: this is Undefined Behavior, and a bad idea
356+
/// // However, it is no-copy
357+
/// let v_transmuted = mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
358+
/// v_orig.clone());
359+
/// // This is the suggested, safe way
360+
/// // It does copy the entire Vector, though, into a new array
361+
/// let v_collected = v_orig.clone()
362+
/// .into_iter()
363+
/// .map(|r| Some(r))
364+
/// .collect::<Vec<Option<&i32>>>();
365+
/// // The no-copy, unsafe way, still using transmute, but not UB
366+
/// // This is equivalent to the original, but safer, and reuses the
367+
/// // same Vec internals. Therefore the new inner type must have the
368+
/// // exact same size, and the same or lesser alignment, as the old
369+
/// // type. The same caveats exist for this method as transmute, for
370+
/// // the original inner type (`&i32`) to the converted inner type
371+
/// // (`Option<&i32>`), so read the nomicon page linked above.
372+
/// let v_from_raw = Vec::from_raw_parts(v_orig.as_mut_ptr(),
373+
/// v_orig.len(),
374+
/// v_orig.capacity());
375+
/// mem::forget(v_orig);
376+
/// ```
378377
///
379-
/// // Copying an `&mut T` to reslice:
380-
/// {
381-
/// fn split_at_mut_transmute<T>(slice: &mut [T], index: usize)
382-
/// -> (&mut [T], &mut [T]) {
383-
/// let len = slice.len();
384-
/// assert!(index < len);
378+
/// Implemententing `split_at_mut`:
379+
/// ```
380+
/// use std::{slice, mem};
381+
/// // There are multiple ways to do this; and there are multiple problems
382+
/// // with the following, transmute, way
383+
/// fn split_at_mut_transmute<T>(slice: &mut [T], index: usize)
384+
/// -> (&mut [T], &mut [T]) {
385+
/// let len = slice.len();
386+
/// assert!(index < len);
387+
/// unsafe {
385388
/// let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
386-
/// (slice[0..index], slice2[index..len])
389+
/// // first: transmute is not typesafe; all it checks is that T and
390+
/// // U are of the same size. Second, right here, you have two
391+
/// // mutable references pointing to the same memory
392+
/// (&mut slice[0..index], &mut slice2[index..len])
387393
/// }
388-
/// // Again, use `as` and reborrowing
389-
/// fn split_at_mut_casts<T>(slice: &mut [T], index: usize)
390-
/// -> (&mut [T], &mut [T]) {
391-
/// let len = slice.len();
392-
/// assert!(index < len);
393-
/// let slice2 = &mut *(slice as *mut [T]); // actually typesafe!
394-
/// (slice[0..index], slice2[index..len])
394+
/// }
395+
/// // This gets rid of the typesafety problems; `&mut *` will *only* give
396+
/// // you an &mut T from an &mut T or *mut T
397+
/// fn split_at_mut_casts<T>(slice: &mut [T], index: usize)
398+
/// -> (&mut [T], &mut [T]) {
399+
/// let len = slice.len();
400+
/// assert!(index < len);
401+
/// unsafe {
402+
/// let slice2 = &mut *(slice as *mut [T]);
403+
/// // however, you still have two mutable references pointing to
404+
/// // the same memory
405+
/// (&mut slice[0..index], &mut slice2[index..len])
406+
/// }
407+
/// }
408+
/// // This is how the standard library does it. This is the best method, if
409+
/// // you need to do something like this
410+
/// fn split_at_stdlib<T>(slice: &mut [T], index: usize)
411+
/// -> (&mut [T], &mut [T]) {
412+
/// let len = self.len();
413+
/// let ptr = self.as_mut_ptr();
414+
/// unsafe {
415+
/// assert!(mid <= len);
416+
/// // This now has three mutable references pointing at the same
417+
/// // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
418+
/// // However, `slice` is never used after `let ptr = ...`, and so
419+
/// // one can treat it as "dead", and therefore, you only have two
420+
/// // real mutable slices.
421+
/// (slice::from_raw_parts_mut(ptr, mid),
422+
/// slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
395423
/// }
396424
/// }
397425
/// ```
@@ -400,39 +428,49 @@ extern "rust-intrinsic" {
400428
///
401429
/// There are valid uses of transmute, though they are few and far between.
402430
///
431+
/// Getting the bitpattern of a floating point type:
432+
/// ```
433+
/// let bitpattern = std::mem::transmute::<f32, u32>(1.0);
434+
/// assert_eq!(bitpattern, 0x3F800000);
403435
/// ```
404-
/// // getting the bitpattern of a floating point type
405-
/// {
406-
/// let x = mem::transmute::<f32, u32>(0.0/0.0)
436+
///
437+
/// Turning a pointer into a function pointer (this isn't guaranteed to
438+
/// work in Rust, although, for example, Linux does make this guarantee):
439+
/// ```
440+
/// fn foo() -> i32 {
441+
/// 0
407442
/// }
443+
/// let pointer = foo as *const ();
444+
/// let function = std::mem::transmute::<*const (), fn() -> i32>(pointer)
445+
/// assert_eq!(function(), 0);
446+
/// ```
408447
///
448+
/// Extending a lifetime, or shortening an invariant an invariant lifetime;
449+
/// this is advanced, very unsafe rust:
450+
/// ```
451+
/// use std::mem;
409452
///
410-
/// // turning a pointer into a function pointer
411-
/// {
412-
/// // in file.c: `int foo(void) { ... }`
413-
/// let handle: *mut libc::c_void = libc::dlopen(
414-
/// b"file.so\0".as_ptr() as *const libc::c_char, libc::RTLD_LAZY);
415-
/// let foo: *mut libc::c_void = libc::dlsym(
416-
/// handle,
417-
/// b"foo\0".as_ptr() as *const libc::c_char);
418-
/// let foo = mem::transmute::<*mut libc::c_void,
419-
/// extern fn() -> libc::c_int>(foo);
420-
/// println!("{}", foo());
453+
/// struct R<'a>(&'a i32);
454+
/// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
455+
/// mem::transmute::<R<'b>, R<'static>>(ptr);
421456
/// }
422457
///
423-
///
424-
/// // extending an invariant lifetime; this is advanced, very unsafe rust
425-
/// {
426-
/// struct T<'a>(&'a i32);
427-
/// let value = 0;
428-
/// let t = T::new(&value);
429-
/// let ptr = &mut t;
430-
/// let ptr_extended = mem::transmute::<&mut T, &mut T<'static>>(ptr);
458+
/// unsafe fn shorten_invariant<'b, 'c>(r: &'b mut R<'static>)
459+
/// -> &'b R<'c> {
460+
/// let ref_to_original =
461+
/// mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(
462+
/// ref_to_extended);
431463
/// }
432464
/// ```
433465
#[stable(feature = "rust1", since = "1.0.0")]
434466
pub fn transmute<T, U>(e: T) -> U;
435467

468+
/// Gives the address for the return value of the enclosing function.
469+
///
470+
/// Using this intrinsic in a function that does not use an out pointer
471+
/// will trigger a compiler error.
472+
pub fn return_address() -> *const u8;
473+
436474
/// Returns `true` if the actual type given as `T` requires drop
437475
/// glue; returns `false` if the actual type provided for `T`
438476
/// implements `Copy`.

0 commit comments

Comments
 (0)