| #![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::back::abi`. |
| |
| /// The representation of a trait object like `&SomeTrait`. |
| /// |
| /// This struct has the same layout as types like `&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 `&SomeTrait`) nor does it control that layout (changing the |
| /// definition will not change the layout of a `&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 (), |
| } |