diff options
Diffstat (limited to 'library/core/src/raw.rs')
| -rw-r--r-- | library/core/src/raw.rs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/library/core/src/raw.rs b/library/core/src/raw.rs new file mode 100644 index 00000000000..741a9dc8797 --- /dev/null +++ b/library/core/src/raw.rs @@ -0,0 +1,86 @@ +#![allow(missing_docs)] +#![unstable(feature = "raw", issue = "27751")] + +//! Contains struct definitions for the layout of compiler built-in types. +//! +//! They can be used as targets of transmutes in unsafe code for manipulating +//! the raw representations directly. +//! +//! Their definition should always match the ABI defined in +//! `rustc_middle::ty::layout`. + +/// The representation of a trait object like `&dyn SomeTrait`. +/// +/// This struct has the same layout as types like `&dyn SomeTrait` and +/// `Box<dyn AnotherTrait>`. +/// +/// `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 `&dyn SomeTrait`) nor does it control that layout (changing the +/// definition will not change the layout of a `&dyn SomeTrait`). It is +/// only designed to be used by unsafe code that needs to manipulate +/// the low-level details. +/// +/// 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`][transmute]. Similarly, the only way to create a true +/// trait object from a `TraitObject` value is with `transmute`. +/// +/// [transmute]: ../intrinsics/fn.transmute.html +/// +/// 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 +/// behavior. +/// +/// # Examples +/// +/// ``` +/// #![feature(raw)] +/// +/// use std::{mem, 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: &dyn 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: &dyn Foo = unsafe { +/// mem::transmute(raw::TraitObject { +/// data: &other_value as *const _ as *mut (), +/// vtable: raw_object.vtable, +/// }) +/// }; +/// +/// // it should work just as if we had constructed a trait object out of +/// // `other_value` directly +/// assert_eq!(synthesized.bar(), 457); +/// ``` +#[repr(C)] +#[derive(Copy, Clone)] +#[allow(missing_debug_implementations)] +pub struct TraitObject { + pub data: *mut (), + pub vtable: *mut (), +} |
