Module xlang_abi::traits

source ·
Expand description

Defines an ABI safe interface for trait objects, by emulating the vtable and fat pointer

ABI Safe Trait Objects

This module provides the low and mid-level api for ABI-Safe Trait objects Most user code will interact with the DynRef, DynMut, and DynBox types. The rest of the api is to support those types and the #[abi_safe] attribute defined by the xlang_abi_macro crate

Defining an ABI Safe Trait

Any trait can be defined as ABI Safe if it meets the following requirements:

  1. The trait must be Object Safe
  2. All trait methods that are not bound by Self: Sized must have an abi-safe receiver (Either &Self, &mut Self, Box, or Pin

    where P is one of the preceeding types)

  3. Every trait method not bound by Self: Sized must be declared with an explicit abi, which should not be extern“Rust“, extern“rust-call“, or extern“rust-intrinsic“
  4. Every trait method bound by Self: Sized must have a default impl (this is required as the #[abi_safe] macro produces code that implements the trait, and can’t implement Self: Sized methods)
  5. Unsafe traits may have additional requirements on the Preconditions of implementors, as the macro produces implementations of the trait that forward to the vtable

Every trait that satisfies the above requirements can use the #[abi_safe] attribute macro to be used with ABI-Safe Trait Object types defined by this library

Example


#[abi_safe]
pub trait Foo{
    fn bar(&self);
    fn baz(&mut self);
}

Using an ABI Safe Trait

Abi safe traits can be used with the DynRef, DynMut, DynBox, and DynPtr types in this module, by calling the unsize_* methods of those types on concrete pointers/references to types implementing the trait (note, this does not work if you have already unsize the type to a language trait object, like &dyn Foo). You can then use these types with the methods of the trait

Manually Implementing AbiSafeTrait

While it is recommend to use the attribute to implement the various AbiSafe traits, it is possible to implement them manually. All of these traits are unsafe and impose numerous preconditions on implmenetors, any of which will result in very unsound code if violated. That being said, if you accept the Nasal Demons you are invoking, it can be fairly simple, and, in some cases, advantageous to implement the traits manually. For example, manual implementations can use additional recievers (usually combined with the arbitrary_self_types feature) or to provide custom implementations of some trait methods for abi-safe trait objects (for example, if the trait is unsafe, and forwarding to the vtable would violate the safety invariant). Manual implementations can also provide custom vtables, including for types that don’t implement the trait, allowing special types to be unsized into references.

Before attempting this, you must ensure the trait in use is object safe, and it is recommended that each method have an explicit abi other than extern“Rust“, extern“rust-call“, or extern“rust-intrinsic“.

Vtables

The first requirement is to create a trait’s abi safe VTable. This must be a #[repr(C)] type, and the first four (non 1-ZST) members must be the members of the AbiSafeVTableHead type (size, alignment, destructor, reserved dellocation function) The remainder of the members should typically be the virtual functions of the trait (the methods not bound on Self: Sized). Each member should be public

Structs

The header of any VTable produced by this module, containing fields common to the vtables of all traits
An abi safe Box to a trait object.
An Abi safe wrapper arround a mutable reference to a trait object
A type that wraps a raw pointer to an abi safe trait object
An Abi safe wrapper arround a shared reference to a trait object

Traits

A valid reciever for a T when using #[xlang_abi::abi_safe_trait]
A trait object type which can be used with the interfaces within this module to be passed safely accros module bounderies.
Types which are VTables for
A trait is used to refer to an abi-safe pointer to a trait object
A type that can be created from a raw pointer erased by this library
Implemented for VTable types that match the layout of VTable<T> defined by the LCRust v0 ABI