How to specify lifetime for associated type


#1
impl<'a, 'b> UpdateWithContext for Application {
    type Context = Context<'a, 'b>;
    
    fn update(&mut self, context: Context<'a, 'b>) {
    }
}

Error:

src/main.rs:62:6: 62:8 error: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates [E0207]
src/main.rs:62 impl<'a, 'b> UpdateWithContext for Application {
                    ^~
src/main.rs:62:6: 62:8 help: run `rustc --explain E0207` to see a detailed explanation
src/main.rs:62:10: 62:12 error: the lifetime parameter `'b` is not constrained by the impl trait, self type, or predicates [E0207]
src/main.rs:62 impl<'a, 'b> UpdateWithContext for Application {
                        ^~

impl UpdateWithContext for Application {
    type Context = for<'a, 'b> Context<'a, 'b>;
    
    fn update<'a, 'b>(&mut self, context: Context<'a, 'b>) {
    }
}

Error:

src/main.rs:63:32: 63:47 error: `Context` is not a trait [E0404]
src/main.rs:63     type Context = for<'a, 'b> Context<'a, 'b>;
                                              ^~~~~~~~~~~~~~~

impl<'a, 'b> UpdateWithContext<Context=Context<'a, 'b>> for Application {
    fn update(&mut self, context: Context<'a, 'b>) {
    }
}

Error:

src/main.rs:62:32: 62:55 error: associated type bindings are not allowed here [E0229]
src/main.rs:62 impl<'a, 'b> UpdateWithContext<Context=Context<'a, 'b>> for Application {
                                              ^~~~~~~~~~~~~~~~~~~~~~~

#2

You can’t, unless the lifetimes are used in the trait signature (UpdateWithContext<'a, 'b>) or in the type it’s implemented for. It’s a limitation of the type system at the moment, but there’s an RFC that tries to change that.


#3

Thanks.


#4

It seems that I am having a similar issue while trying to write a trait using an associated type bounded by the iterator trait: https://play.rust-lang.org/?gist=4dd80a8d723458d182b1f21f0f87a145&version=stable

I tried to introduce lifetimes in the trait signature following the compiler advice one by one. But it seems that I am forced toward the following annotations:

trait Greedy<'a> {
    type Trans; // transformation
    type TransIterator: Iterator<Item = Self::Trans>;
    
    fn iter_trans(&'a self) -> Self::TransIterator;
    
    fn is_ok(&self, t: &Self::Trans) -> bool;
    
    fn apply(&mut self, t: &Self::Trans);
    
    fn run(&'a mut self) {
        loop {
            let t = self.iter_trans().find(|t| self.is_ok(t));
            if t.is_some() {
                self.apply(&t.unwrap())
            } else {
                break
            }
        }
    }
}

And this does not compile as fn run the are a mutable borrow and an immutable borrow with overlapping (same) lifetimes.

Am I doing something wrong? Is there a way around it?


#5

You’re not doing anything wrong - you need that GAT feature as well. Barring that, you can change the &mut self requirement to &self and probably get away with the lifetime parameter on the trait, as you have it in the snippet. This changes semantics (and would require interior mutability for the impls) of course so might not be workable.


#6

Thanks!