Help with impl has extra requirement `for<'r> impl Fn...`

Hello Rustaceans!

I'm using the Oxigraph crate, a triplestore, that has several different implementations of the backend store, corresponding to different actual storage methods (in memory, Sled, etc).

I am ultimately trying to make a trait that can unify these different types, but for the purposes of my question, I've made a toy example that fails to compile in the same way I'm experiencing.

Here's the playground: Rust Playground

Essentially, there's a ThirdPartyTarget that has a method foo:

use core::marker::PhantomData;

struct Transaction<'a> {
    marker: PhantomData<&'a ()>
}
struct Out;
struct ThirdPartyTarget;
impl ThirdPartyTarget { // Can't modify this impl, third-party library
    fn foo(&self, _f: impl Fn(Transaction<'_>) -> Out) -> Out {
        unimplemented!()
    }
}

foo receives a function that takes a Transaction. So to proxy this, I made a trait like this:

trait Proxy<T> {
    fn foo(&self, f: impl Fn(T) -> Out) -> Out;
}

And an implementation:

impl Proxy<Transaction<'_>> for ThirdPartyTarget {
    fn foo(&self, f: impl Fn(Transaction<'_>) -> Out) -> Out {
        self.foo(f)
    }
}

But because Transaction requires a lifetime, I get the compile error:

impl has extra requirement `for<'r> impl Fn(Transaction<'_>) -> Out: Fn<(Transaction<'r>,)>`

How can I fix the trait definition to allow for the lifetime generically, or how can I fix the impl so that it actually conforms to my trait?

Thanks for any tips!

I managed something that compiles:

trait Proxy<F> {
    fn foo(&self, f: F) -> Out;
}

impl<F> Proxy<F> for ThirdPartyTarget
where F: Fn(Transaction<'_>) -> Out
{
    fn foo(&self, f: F) -> Out {
        self.foo(f)
    }
}

But this is not perfect as it changes the Proxy trait :frowning:

1 Like

Wow thanks! This helps!

Something like:

trait Proxy<F, T, R, I, E> 
    where 
        F: Fn(T) -> Result<R, I> {

    fn foo(&self, f: F) -> Result<R, E>;
}

Seems to work as well!

1 Like