# Trait with associated type with lifetime

I am trying to generalize some logic with traits. Part of the logic is common, some is not. The common logic I am trying to address via traits, but I am not able to (lifetimes inside associated types?).

The gist is: that there is logic that depends on `&B` below, but the lifetime of `&B` is not easily mapped to the trait system.

Is there an idiomatic way of avoiding this?

``````// a struct that we receive as a reference
struct B {
b: usize
}

// under some conditions, we need to use this state
struct State1<'a> {
b: &'a B,
inner: usize,
}

// under some conditions, we need to use this state
struct State2<'a> {
b: &'a B,
inner: usize,
inner1: usize,
}

// that share common semathics
trait State<'a> {
}

impl<'a> State<'a> for State1<'a> {
self.inner += 1;
}
}

impl<'a> State<'a> for State2<'a> {
self.inner += 1;
self.inner1 += 2;
}
}

// The common logic is described in a trait
trait A {
type State: State<'a>;  // <- the problem

fn build_state(b: &'a B) -> Self::State;
fn use_state(b: Self::State) -> usize;
}

// an example of an implementation of the common logic
struct A1 {}
impl<'a>  A for A1 {
type State = State1<'a>;

fn build_state(b: &'a B) -> State1<'a> {
State1 {
b
}
}
fn use_state(b: Self::State) -> usize {
b.b + b.inner
}
}

// a second example of an implementation of the common logic
struct A2 {}
impl<'a> A for A2 {
type State = State2<'a>;

fn build_state(b: &'a B) -> State1<'a> {
State2 {
b
}
}
fn use_state(b: Self::State) -> usize {
b.b + b.inner + b.inner1
}
}

// the common behavior across traits
fn bla<T: A>(v: &B) -> usize {
let state = T::build_state(v);

state.add(10); // common logic from state. More complex than this...

T::use_state(state)
}

fn main() {
// we are provided with a ref, not with the owned struct
let b = &B{b: 100};

// the decision over which logic to use is known at runtime and we can branch it, like so:
let a1 = bla::<A1>(b);
let ab = bla::<A2>(b);
}
``````

Try this:

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.