about summary refs log tree commit diff
path: root/library/core/src/raw.rs
diff options
context:
space:
mode:
Diffstat (limited to 'library/core/src/raw.rs')
-rw-r--r--library/core/src/raw.rs86
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 (),
+}