21
21
use marker:: Copy ;
22
22
use mem;
23
23
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
+ /// ```
25
58
#[ repr( C ) ]
26
59
pub struct Slice < T > {
27
60
pub data : * const T ,
@@ -30,18 +63,88 @@ pub struct Slice<T> {
30
63
31
64
impl < T > Copy for Slice < T > { }
32
65
33
- /// The representation of a Rust closure
66
+ /// The representation of an old closure.
34
67
#[ repr( C ) ]
35
68
#[ 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" ) ]
36
73
pub struct Closure {
37
74
pub code : * mut ( ) ,
38
75
pub env : * mut ( ) ,
39
76
}
40
77
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
+ /// };
42
143
///
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
+ /// ```
45
148
#[ repr( C ) ]
46
149
#[ derive( Copy ) ]
47
150
pub struct TraitObject {
@@ -51,7 +154,7 @@ pub struct TraitObject {
51
154
52
155
/// This trait is meant to map equivalences between raw structs and their
53
156
/// corresponding rust values.
54
- pub trait Repr < T > {
157
+ pub unsafe trait Repr < T > {
55
158
/// This function "unwraps" a rust value (without consuming it) into its raw
56
159
/// struct representation. This can be used to read/write different values
57
160
/// for the struct. This is a safe method because by default it does not
@@ -60,5 +163,5 @@ pub trait Repr<T> {
60
163
fn repr ( & self ) -> T { unsafe { mem:: transmute_copy ( & self ) } }
61
164
}
62
165
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