about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2015-02-15 18:22:31 +0530
committerManish Goregaokar <manishsmail@gmail.com>2015-02-15 18:22:31 +0530
commit8cc3fbd41dddbb11f442a17902cd0d276aa22566 (patch)
treee161c7ec52efc9aad02a2ac2979b30b9aa606814 /src
parent63091efa3bdcb18a6fac8af48acfa5634087624b (diff)
parent7a52932f4cd65f57bcc8d77f12e32066b2a9c432 (diff)
downloadrust-8cc3fbd41dddbb11f442a17902cd0d276aa22566.tar.gz
rust-8cc3fbd41dddbb11f442a17902cd0d276aa22566.zip
Rollup merge of #22218 - huonw:raw-docs, r=steveklabnik,huonw
This overhauls the very meager docs that currently exist to clarify
various understandable confusions that I've noticed, e.g. people look in
`std::raw` for the "real" types of slices like `&[T]`, or think that
`Slice<T>` refers to `[T]` (fixes #22214).

This patch takes the liberty of offering some "style" guidance around
`raw::Slice`, since there's more restricted ways to duplicate all
functionality connected to it: `std::slice::from_raw_parts{,_mut}` for
construction and `.as_{,mut_}ptr` & `.len` for deconstruction.

It also deprecates the `std::raw::Closure` type which is now useless for
non-type-erased closures, and replaced by `TraitObject` for `&Fn`, `&mut
FnMut` etc, so I guess it should be called a:

[breaking-change]
Diffstat (limited to 'src')
-rw-r--r--src/libcore/raw.rs119
1 files changed, 111 insertions, 8 deletions
diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs
index 3fd244b46e3..bb0c22d3561 100644
--- a/src/libcore/raw.rs
+++ b/src/libcore/raw.rs
@@ -21,7 +21,40 @@
 use marker::Copy;
 use mem;
 
-/// The representation of a Rust slice
+/// The representation of a slice like `&[T]`.
+///
+/// This struct is guaranteed to have the layout of types like `&[T]`,
+/// `&str`, and `Box<[T]>`, but is not the type of such slices
+/// (e.g. the fields are not directly accessible on a `&[T]`) nor does
+/// it control that layout (changing the definition will not change
+/// the layout of a `&[T]`). It is only designed to be used by unsafe
+/// code that needs to manipulate the low-level details.
+///
+/// However, it is not recommended to use this type for such code,
+/// since there are alternatives which may be safer:
+///
+/// - Creating a slice from a data pointer and length can be done with
+///   `std::slice::from_raw_parts` or `std::slice::from_raw_parts_mut`
+///   instead of `std::mem::transmute`ing a value of type `Slice`.
+/// - Extracting the data pointer and length from a slice can be
+///   performed with the `as_ptr` (or `as_mut_ptr`) and `len`
+///   methods.
+///
+/// If one does decide to convert a slice value to a `Slice`, the
+/// `Repr` trait in this module provides a method for a safe
+/// conversion from `&[T]` (and `&str`) to a `Slice`, more type-safe
+/// than a call to `transmute`.
+///
+/// # Examples
+///
+/// ```
+/// use std::raw::{self, Repr};
+///
+/// let slice: &[u16] = &[1, 2, 3, 4];
+///
+/// let repr: raw::Slice<u16> = slice.repr();
+/// println!("data pointer = {:?}, length = {}", repr.data, repr.len);
+/// ```
 #[repr(C)]
 pub struct Slice<T> {
     pub data: *const T,
@@ -30,18 +63,88 @@ pub struct Slice<T> {
 
 impl<T> Copy for Slice<T> {}
 
-/// The representation of a Rust closure
+/// The representation of an old closure.
 #[repr(C)]
 #[derive(Copy)]
+#[unstable(feature = "core")]
+#[deprecated(reason = "unboxed new closures do not have a universal representation; \
+                       `&Fn` (etc) trait objects should use `TraitObject` instead",
+             since= "1.0.0")]
 pub struct Closure {
     pub code: *mut (),
     pub env: *mut (),
 }
 
-/// The representation of a Rust trait object.
+/// The representation of a trait object like `&SomeTrait`.
+///
+/// This struct has the same layout as types like `&SomeTrait` and
+/// `Box<AnotherTrait>`. The [Static and Dynamic Dispatch chapter of the
+/// Book][moreinfo] contains more details about the precise nature of
+/// these internals.
+///
+/// [moreinfo]: ../../book/static-and-dynamic-dispatch.html#representation
+///
+/// `TraitObject` is guaranteed to match layouts, but it is not the
+/// type of trait objects (e.g. the fields are not directly accessible
+/// on a `&SomeTrait`) nor does it control that layout (changing the
+/// definition will not change the layout of a `&SometTrait`). It is
+/// only designed to be used by unsafe code that needs to manipulate
+/// the low-level details.
+///
+/// There is no `Repr` implementation for `TraitObject` because there
+/// is no way to refer to all trait objects generically, so the only
+/// way to create values of this type is with functions like
+/// `std::mem::transmute`. Similarly, the only way to create a true
+/// trait object from a `TraitObject` value is with `transmute`.
+///
+/// Synthesizing a trait object with mismatched types—one where the
+/// vtable does not correspond to the type of the value to which the
+/// data pointer points—is highly likely to lead to undefined
+/// behaviour.
+///
+/// # Examples
+///
+/// ```
+/// use std::mem;
+/// use std::raw;
+///
+/// // an example trait
+/// trait Foo {
+///     fn bar(&self) -> i32;
+/// }
+/// impl Foo for i32 {
+///     fn bar(&self) -> i32 {
+///          *self + 1
+///     }
+/// }
+///
+/// let value: i32 = 123;
+///
+/// // let the compiler make a trait object
+/// let object: &Foo = &value;
+///
+/// // look at the raw representation
+/// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
+///
+/// // the data pointer is the address of `value`
+/// assert_eq!(raw_object.data as *const i32, &value as *const _);
+///
+///
+/// let other_value: i32 = 456;
+///
+/// // construct a new object, pointing to a different `i32`, being
+/// // careful to use the `i32` vtable from `object`
+/// let synthesized: &Foo = unsafe {
+///      mem::transmute(raw::TraitObject {
+///          data: &other_value as *const _ as *mut (),
+///          vtable: raw_object.vtable
+///      })
+/// };
 ///
-/// This struct does not have a `Repr` implementation
-/// because there is no way to refer to all trait objects generically.
+/// // it should work just like we constructed a trait object out of
+/// // `other_value` directly
+/// assert_eq!(synthesized.bar(), 457);
+/// ```
 #[repr(C)]
 #[derive(Copy)]
 pub struct TraitObject {
@@ -51,7 +154,7 @@ pub struct TraitObject {
 
 /// This trait is meant to map equivalences between raw structs and their
 /// corresponding rust values.
-pub trait Repr<T> {
+pub unsafe trait Repr<T> {
     /// This function "unwraps" a rust value (without consuming it) into its raw
     /// struct representation. This can be used to read/write different values
     /// for the struct. This is a safe method because by default it does not
@@ -60,5 +163,5 @@ pub trait Repr<T> {
     fn repr(&self) -> T { unsafe { mem::transmute_copy(&self) } }
 }
 
-impl<T> Repr<Slice<T>> for [T] {}
-impl Repr<Slice<u8>> for str {}
+unsafe impl<T> Repr<Slice<T>> for [T] {}
+unsafe impl Repr<Slice<u8>> for str {}