I am having trouble with lifetime bounds in the following code.
There is a Space
type with an Element
associated type and a function do_stuff
that takes an IntoIterator
of element references. I am trying to implement a generic OptionSpace
whose elements are Option<S::Element>
for S: Space
.
In the implementation for OptionSpace<S>::do_stuff
, the compiler complains that it wants S::Element: 'a
in order to guarantee that Option<S::Element>: 'a
even though I have bounded Self::Element: 'a
and Self::Element = Option<S::Element>
. If I change the bounds to S::Element: 'a
then the method interface is different, which is also an error.
pub trait Space {
type Element;
fn do_stuff<'a, I>(&self, elements: I)
where
I: IntoIterator<Item = &'a Self::Element>,
Self::Element: 'a;
}
pub struct OptionSpace<S> {
pub inner: S,
}
impl<S: Space> Space for OptionSpace<S> {
type Element = Option<<S as Space>::Element>;
// type Element = Vec<<S as Space>::Element>; // Also fails
// type Element = <S as Space>::Element; // Works
fn do_stuff<'a, I>(&self, _elements: I)
where
I: IntoIterator<Item = &'a Self::Element>,
Self::Element: 'a,
// <Self as Space>::Element: 'a, // same error
// Option<<S as Space>::Element>: 'a, // same error
{
}
}
This results in
error[E0309]: the associated type `<S as Space>::Element` may not live long enough
--> src/main.rs:21:25
|
21 | I: IntoIterator<Item = &'a Self::Element>,
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: consider adding an explicit lifetime bound `<S as Space>::Element: 'a`...
= note: ...so that the reference type `&'a Option<<S as Space>::Element>` does not outlive the data it points at
I get that S::Element
might not live for 'a
at the impl
-level but since Self::Element: 'a
is part of the bound on do_stuff
shouldn't that just mean that do_stuff
won't be available?
Some things that I have tried
- (Fails, interface mismatch) Replacing / adding the suggested
<S as Space>::Element: 'a
bound. - (Fails, same lifetime error) Use
Element = Vec<S::Element>
instead ofOption<...>
. - (Works) Use
Element = S::Element
instead ofOption<...>
. - (Works) Taking a single
&'a Self::Element
as an argument instead of an iterator - (Works) Use a concrete inner type instead of generic
S
, e.g.Element = Option<i64>
// This works fine
pub struct OptionIntSpace;
impl Space for OptionIntSpace {
type Element = Option<i64>;
fn do_stuff<'a, I>(&self, _elements: I)
where
I: IntoIterator<Item = &'a Self::Element>,
Self::Element: 'a {}
}
Is anyone able to help me understand what is going wrong or how I can get it to work?
If it is the case that the lifetime bounds on Space::do_stuff
should be expressed differently, it might be helpful to know that in my actual code do_stuff
returns a value but that value does not depend on 'a
.
Thanks for taking the time to read this!