2121use marker:: Copy ;
2222use mem;
2323
24- /// The representation of a Rust slice
24+ /// The representation of a slice like `&[T]`.
25+ ///
26+ /// This struct is guaranteed to have the layout of types like `&[T]`,
27+ /// `&str`, and `Box<[T]>`, but is not the type of such slices
28+ /// (e.g. the fields are not directly accessible on a `&[T]`) nor does
29+ /// it control that layout (changing the definition will not change
30+ /// the layout of a `&[T]`). It is only designed to be used by unsafe
31+ /// code that needs to manipulate the low-level details.
32+ ///
33+ /// However, it is not recommended to use this type for such code,
34+ /// since there are alternatives which may be safer:
35+ ///
36+ /// - Creating a slice from a data pointer and length can be done with
37+ /// `std::slice::from_raw_parts` or `std::slice::from_raw_parts_mut`
38+ /// instead of `std::mem::transmute`ing a value of type `Slice`.
39+ /// - Extracting the data pointer and length from a slice can be
40+ /// performed with the `as_ptr` (or `as_mut_ptr`) and `len`
41+ /// methods.
42+ ///
43+ /// If one does decide to convert a slice value to a `Slice`, the
44+ /// `Repr` trait in this module provides a method for a safe
45+ /// conversion from `&[T]` (and `&str`) to a `Slice`, more type-safe
46+ /// than a call to `transmute`.
47+ ///
48+ /// # Examples
49+ ///
50+ /// ```
51+ /// use std::raw::{self, Repr};
52+ ///
53+ /// let slice: &[u16] = &[1, 2, 3, 4];
54+ ///
55+ /// let repr: raw::Slice<u16> = slice.repr();
56+ /// println!("data pointer = {:?}, length = {}", repr.data, repr.len);
57+ /// ```
2558#[ repr( C ) ]
2659pub struct Slice < T > {
2760 pub data : * const T ,
@@ -30,18 +63,88 @@ pub struct Slice<T> {
3063
3164impl < T > Copy for Slice < T > { }
3265
33- /// The representation of a Rust closure
66+ /// The representation of an old closure.
3467#[ repr( C ) ]
3568#[ derive( Copy ) ]
69+ #[ unstable( feature = "core" ) ]
70+ #[ deprecated( reason = "unboxed new closures do not have a universal representation; \
71+ `&Fn` (etc) trait objects should use `TraitObject` instead",
72+ since= "1.0.0" ) ]
3673pub struct Closure {
3774 pub code : * mut ( ) ,
3875 pub env : * mut ( ) ,
3976}
4077
41- /// The representation of a Rust trait object.
78+ /// The representation of a trait object like `&SomeTrait`.
79+ ///
80+ /// This struct has the same layout as types like `&SomeTrait` and
81+ /// `Box<AnotherTrait>`. The [Static and Dynamic Dispatch chapter of the
82+ /// Book][moreinfo] contains more details about the precise nature of
83+ /// these internals.
84+ ///
85+ /// [moreinfo]: ../../book/static-and-dynamic-dispatch.html#representation
86+ ///
87+ /// `TraitObject` is guaranteed to match layouts, but it is not the
88+ /// type of trait objects (e.g. the fields are not directly accessible
89+ /// on a `&SomeTrait`) nor does it control that layout (changing the
90+ /// definition will not change the layout of a `&SometTrait`). It is
91+ /// only designed to be used by unsafe code that needs to manipulate
92+ /// the low-level details.
93+ ///
94+ /// There is no `Repr` implementation for `TraitObject` because there
95+ /// is no way to refer to all trait objects generically, so the only
96+ /// way to create values of this type is with functions like
97+ /// `std::mem::transmute`. Similarly, the only way to create a true
98+ /// trait object from a `TraitObject` value is with `transmute`.
99+ ///
100+ /// Synthesizing a trait object with mismatched types—one where the
101+ /// vtable does not correspond to the type of the value to which the
102+ /// data pointer points—is highly likely to lead to undefined
103+ /// behaviour.
104+ ///
105+ /// # Examples
106+ ///
107+ /// ```
108+ /// use std::mem;
109+ /// use std::raw;
110+ ///
111+ /// // an example trait
112+ /// trait Foo {
113+ /// fn bar(&self) -> i32;
114+ /// }
115+ /// impl Foo for i32 {
116+ /// fn bar(&self) -> i32 {
117+ /// *self + 1
118+ /// }
119+ /// }
120+ ///
121+ /// let value: i32 = 123;
122+ ///
123+ /// // let the compiler make a trait object
124+ /// let object: &Foo = &value;
125+ ///
126+ /// // look at the raw representation
127+ /// let raw_object: raw::TraitObject = unsafe { mem::transmute(object) };
128+ ///
129+ /// // the data pointer is the address of `value`
130+ /// assert_eq!(raw_object.data as *const i32, &value as *const _);
131+ ///
132+ ///
133+ /// let other_value: i32 = 456;
134+ ///
135+ /// // construct a new object, pointing to a different `i32`, being
136+ /// // careful to use the `i32` vtable from `object`
137+ /// let synthesized: &Foo = unsafe {
138+ /// mem::transmute(raw::TraitObject {
139+ /// data: &other_value as *const _ as *mut (),
140+ /// vtable: raw_object.vtable
141+ /// })
142+ /// };
42143///
43- /// This struct does not have a `Repr` implementation
44- /// because there is no way to refer to all trait objects generically.
144+ /// // it should work just like we constructed a trait object out of
145+ /// // `other_value` directly
146+ /// assert_eq!(synthesized.bar(), 457);
147+ /// ```
45148#[ repr( C ) ]
46149#[ derive( Copy ) ]
47150pub struct TraitObject {
@@ -51,7 +154,7 @@ pub struct TraitObject {
51154
52155/// This trait is meant to map equivalences between raw structs and their
53156/// corresponding rust values.
54- pub trait Repr < T > {
157+ pub unsafe trait Repr < T > {
55158 /// This function "unwraps" a rust value (without consuming it) into its raw
56159 /// struct representation. This can be used to read/write different values
57160 /// for the struct. This is a safe method because by default it does not
@@ -60,5 +163,5 @@ pub trait Repr<T> {
60163 fn repr ( & self ) -> T { unsafe { mem:: transmute_copy ( & self ) } }
61164}
62165
63- impl < T > Repr < Slice < T > > for [ T ] { }
64- impl Repr < Slice < u8 > > for str { }
166+ unsafe impl < T > Repr < Slice < T > > for [ T ] { }
167+ unsafe impl Repr < Slice < u8 > > for str { }
0 commit comments