amplify

Module strategy

Source
Expand description

This is a trick for rust compiler helping to distinguish types implementing mutually-exclusive traits (required until negative trait impls will be there) Implemented after concept by Martin Habovštiak martin.habovstiak@gmail.com

The module proposes generic implementation strategies, which allow multiple generic trait implementations.

Implementing trait for a generic type (“blanket implementation”) more than once (applies both for local and foreign traits) - or implement foreign trait for a concrete type where there is some blanket implementation in the upstream. The solution is to use special pattern by @Kixunil. I use it widely and have a special helper type in src/strategy.rssrc/strategy.rs module.

With that helper type you can write the following code, which will provide you with efficiently multiple blanket implementations of some trait SampleTrait:

pub trait SampleTrait {
    fn sample_trait_method(&self);
}

// Define strategies, one per specific implementation that you need,
// either blanket or concrete
pub struct StrategyA;
pub struct StrategyB;
pub struct StrategyC;

// Define a single marker type
pub trait Strategy {
    type Strategy;
}

// Do a single blanket implementation using Holder and Strategy marker trait
impl<T> SampleTrait for T
where
    T: Strategy,
    for<'a> amplify::Holder<&'a T, T::Strategy>: SampleTrait,
{
    // Do this for each of sample trait methods:
    fn sample_trait_method(&self) {
        amplify::Holder::new(self).sample_trait_method()
    }
}

// Do this type of implementation for each of the strategies
impl<'a, T> SampleTrait for amplify::Holder<&'a T, StrategyA>
where
    T: Strategy,
{
    fn sample_trait_method(&self) {
        /* write your implementation-specific code here accessing type data,
        when needed, via `self.as_inner()` */
    }
}

// Finally, apply specific implementation strategy to a concrete type
// (or do it in a blanket generic way) as a marker:
impl Strategy for ConcreteTypeA {
    type Strategy = StrategyA;
}

Structs§

  • Helper type allowing implementation of trait object for generic types multiple times. In practice this type is never used