Skip to content
Test repository for trait delegation support in rust.
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Test repository for trait delegation support in rust.

Demonstrates how to use the experimental proc macro defined in delegable-derive to delegate the implementation of a trait for a type to a field of that type.

Other examples are available, including delegation to a "Vec-like trait" in the example directory of delegable-derive.

How it works

The general approach of the macro is the following:

  • Mark a trait Tr that can be derived as #[delegable]. This is required to generate a "delegation trait" TrDelegable for Tr without compiler support.
  • Implement the delegation trait TrDelegable for the type T that whishes to delegate the implementation of Tr to a field or method.
  • Use Tr in code and calls Tr methods on T.

Organization of the repository

├── boss-type # type that delegates to the "worker trait"
├── src # "main"
├── worker-trait # trait whose implementation we delegate
└── worker-type # type that implements the "worker trait"

Main parts

Work trait

    use delegable_derive::delegable;

    // Trait to be delegated
    pub trait Work
        fn do_work(&self) -> u64;

        fn do_nothing(&self);

        fn change_worker(&mut self);

        fn into_work(self) -> u64;

        fn clone_worker(&self) -> Self;

        fn increment_worker(&mut self, x: u64);

Worker type

    use worker_trait::work::Work;

    pub struct Worker {
        x: u64,
        y: u64

    impl Work for Worker {
        // ... actual implementation omitted ...

Boss struct

    pub struct Boss {
        worker : Worker

    impl work::delegate_Work for Boss {
        type Inner = Worker;

        fn inner(&self) -> &Self::Inner { &self.worker }
        fn inner_mut(&mut self) -> &mut Self::Inner { &mut self.worker }
        fn into_inner(self) -> Self::Inner { self.worker }
        fn from_inner(delegate: Self::Inner) -> Self { Boss { worker : delegate }}

The main using Boss

use worker_trait::work::Work;

// accepts some types that implements Work
fn print_work<T :use worker_trait::work::Work;

fn print_work<T : Work>(worker: &T) {
    println!("Here is my work: {}", worker.do_work());

fn main() {
    use boss_type::boss::Boss;

    let boss = Boss::new(20, 21);
    print_work(&boss); // this works
    let mut boss = boss;
    boss.change_worker(); // can call direct method of the trait too
    let second_boss = boss.clone_worker();
    println!("Here is my final work: {}", second_boss.into_work());

Current limitations

The current implementation is meant as a quick proof-of-concept. It particular, it exhibits the following limitations:

  • Having to mark delegable trait
  • No delegation of struct (could be a natural extension with inherent traits).
  • Having to implement the delegable trait, which can be more boilerplate than implementing the original trait! This could be alleviated with macros for common cases (e.g., delegating MyTrait to a field with a delegate!(self.x, MyTrait)).
  • The proc macro doesn't properly report errors yet.
  • The proc macro doesn't use explicit call syntax with <self as Trait>::method(...) everywhere, which may cause problems in some cases.
  • I'm unsure if the delegation trait should always expose into_inner, or only when required by the trait, or never and fail for traits needing this.
  • Currently no support of associated traits or constants, as I didn't look into it.
  • The generation of the delegation trait is not clean at all: can conflict with other items in the namespace. Plus, the generated trait name must be "guessed" by the user at the moment.
  • Proc macro means nighty only.
You can’t perform that action at this time.