5 releases

0.1.4 Oct 12, 2020
0.1.3 Oct 12, 2020
0.1.2 Oct 12, 2020
0.1.1 Oct 10, 2020
0.1.0 Oct 10, 2020

#1631 in Rust patterns

MIT/Apache

12KB
129 lines

trait-union

crates.io docs.rs

This crate provides a macro that generates a trait-union type. That is, a trait object type which can contain any one of a pre-determined set of implementors.

The generated type does not allocate. The size of the type is the size of the largest variant plus some constant overhead.

NOTE: As of rustc 1.47, you must enable the untagged_unions feature to store non-Copy types in a trait-union. This will change soon.

Example

use trait_union::trait_union;
use std::fmt::Display;

trait_union! {
    /// Container can contain either an i32, a &'static str, or a bool.
    union Container: Display = i32 | &'static str | bool;
}

let mut container = Container::new(32);
assert_eq!(container.to_string(), "32");

container = Container::new("Hello World");
assert_eq!(container.to_string(), "Hello World");

container = Container::new(true);
assert_eq!(container.to_string(), "true");

Implementation

The generated type looks roughly as follows:

struct Container {
    data: union {
        variant1: i32,
        variant2: &'static str,
        variant3: bool,
    },
    vtable: *mut (),
}

Its size is therefore similar to the size of an enum with one variant per implementor. Depending on the number of implementors, compile times should be significantly lower than with an enum. The run-time performance is similar to that of Box<dyn Trait>.

License

This project is licensed under either of

  • Apache License, Version 2.0
  • MIT License

at your option.

Dependencies

~1.5MB
~38K SLoC