Implementation of trait not general enough since I can't specify small enough lifetime

71 views Asked by At

(This is a bit of a long one, since I'm not exactly sure where exactly the error is, sorry!)

I have a trait

trait FilterComponent<'a, F>: Sized {
    fn from_option(f: Option<&'a F>) -> Option<Self>;
}

which I am using to get a &F from an external crate and convert it into a type such as Option<&F> or &F, returning a Err(()) in the case where the conversion is not desirable. I then pass the unwrapped value (if it is Some) to a function that takes that implementing type. I'll stick with the implementation for just a &F

impl<'a: 'b, 'b, F> FilterComponent<'a, F> for &'b F {
    fn from_option(f: Option<&'a F>) -> Option<Self> {
        f
    }
}

Since I want to do this for a list of functions, each with potentially different choices of FilterComponent, I create a series of traits to turn a general function into one I can sue, as follows:

//the type that implements GraphFilter and is returned by the IntoGraphFilter trait
struct FunctionFilter<F, G, Func>
where
    G: for<'a> FilterComponent<'a, F>,
    Func: Fn(G) -> bool,
{
    func: Func,
    _phantom: PhantomData<(F, G)>,
}

//trait to turn a function into a nameable type we can implement the
//typeless GraphFilter trait for (to avoid unconstrained type parameters)
trait IntoGraphFilter<F, G> {
    type Output: GraphFilter;
    fn into_filter(self) -> Self::Output;
}

impl<F, G, Func> IntoGraphFilter<F, G> for Func
where
    G: for<'a> FilterComponent<'a, F>,
    Func: Fn(G) -> bool,
{
    type Output = FunctionFilter<F, G, Func>;
    fn into_filter(self) -> Self::Output {
        FunctionFilter {
            func: self,
            _phantom: PhantomData,
        }
    }
}

impl<F, G, Func> GraphFilter for FunctionFilter<F, G, Func>
where
    G: for<'a> FilterComponent<'a, F>,
    Func: Fn(G) -> bool,
{
}

//The final trait I use to store my generic functions
trait GraphFilter {}

//The storing struct
struct Storer {
    filters: Vec<Box<dyn GraphFilter>>,
}

impl Storer {
    fn new() -> Self {
        Self {
            filters: Vec::new(),
        }
    }
    fn add_filter<F, G: for<'a> FilterComponent<'a, F>>(
        &mut self,
        func: impl IntoGraphFilter<F, G>,
    ) {
        self.filters.push(Box::new(func.into_filter()))
    }
}

fn main() {
    Storer::new().add_filter(|foo: &()| true);
}

Then, since I want to store these filters dynamically, I have some struct that stores dyn GraphFilters in a Vec within some struct. To add them, I have a function impl'd for this struct with the signature:

fn add_filter<F, G: for<'a> FilterComponent<'a, F>>(&mut self, filter: impl IntoGraphFilter<F, G>)

But when I try to actually use this function like so:

storage.add_filter(|foo: &Foo| {false});

I get the error: "implementation of FilterComponent is not general enough FilterComponent<'0, Foo> would have to be implemented for the type &Foo, for any lifetime '0... ...but FilterComponent<'1, Foo> is actually implemented for the type &'1 Foo, for some specific lifetime '1" Looking at my impl for &F, I only get FilterComponent<'a, F> for 'a longer than my types own lifetime, which in the case of |foo: &Foo| {false} should be any lifetime. I'm not really sure where to go from here: I've tried modifying everything to remove the for<'a> but I ended up with an error that 'a is trying to outlive 'static

Edit: In editing to make reproducible, the compiler is now also telling me that my associated type won't live long enough in the definition of add_filter, which is a problem I had previously encountered but only seems to show up occasionaly, probably being hidden by other errors - any hints for fixing this would be appreciated too!

0

There are 0 answers