Issue with trait and lifetime, implementation of X is not general enough

Hi, I've an issue with a definition for a lifetime for a trait... supposing that Extern is an external not modifiable struct (with all related functions), this is the example code generated for a minimal sample in Playground here.

Actual code:

use anyhow::Error;

struct Extern {}

impl Extern {
    fn something<T, E, F>(f: F) -> Result<T, E>
    where
        F: FnOnce(&mut Self) -> Result<T, E>,
        E: From<Error>,
    {
        f(&mut Extern {})
    }
}

trait TestInterface<'a> {
    fn new(test: &'a Test, test_mut_reference: &'a mut Extern) -> Self;

    fn something<S, T, E, F>(&mut self, f: F) -> Result<T, E>
    where
        F: FnOnce(S) -> Result<T, E>,
        E: From<Error>,
        for<'b> S: TestInterface<'b>;
}

struct Test {}

impl<'a> TestInterface<'a> for Test {
    fn new(_test: &'a Test, _test_mut_reference: &'a mut Extern) -> Self {
        Self {}
    }
    
    fn something<S, T, E, F>(&mut self, f: F) -> Result<T, E>
    where
        F: FnOnce(S) -> Result<T, E>,
        E: From<Error>,
        for<'b> S: TestInterface<'b>,
    {
        Extern::something::<T, E, _>(|t| f(S::new(self, t)))
    }
}

struct TestWithTest<'a> {
    test: &'a Test,
    test_mut_reference: &'a mut Extern,
}

impl<'a> TestInterface<'a> for TestWithTest<'a> {
    fn new(test: &'a Test, test_mut_reference: &'a mut Extern) -> Self {
        Self {
            test,
            test_mut_reference
        }
    }

    fn something<S, T, E, F>(&mut self, f: F) -> Result<T, E>
    where
        F: FnOnce(S) -> Result<T, E>,
        E: From<Error>,
        for<'b> S: TestInterface<'b>,
    {
        f(S::new(self.test, self.test_mut_reference))
    }
}

fn main() {
    let mut test = Test {};
    
    let _: Result<_, Error> = test.something(|_: TestWithTest| Ok(()));
}

Could someone help me understanding what the compiler is trying to say and how to fix this error?

Output error is:

error: implementation of `TestInterface` is not general enough
  --> src/main.rs:68:31
   |
68 |     let _: Result<_, Error> = test.something(|_: TestWithTest| Ok(()));
   |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `TestInterface` is not general enough
   |
   = note: `TestInterface<'0>` would have to be implemented for the type `TestWithTest<'_>`, for any lifetime `'0`...
   = note: ...but `TestInterface<'1>` is actually implemented for the type `TestWithTest<'1>`, for some specific lifetime `'1`

error: could not compile `playground` due to previous error

Thanks in advance :slight_smile:

This bound on TestInterface::something:

for<'b> S: TestInterface<'b>;

requires that S implements the trait for all lifetimes, but each TestWithTest<'a> only implements TestInterface<'a>. And given the new function, it can never satisfy that bound. (Types that differ by lifetime only are still distinct types; TestWithTest without an assigned lifetime is a type constructor, not a type.)

You can try making that method lifetime-specific like new is. (I'm not sure it will work and sorry for not trying myself - on mobile.)

1 Like

I'm not sure if I got it correctly but also adding to TestInterface::something a specific function lifetime doesn't satisfy the required bounds :frowning:

The compiler say something similar:

37 |     fn something<'b, S, T, E, F>(&mut self, f: F) -> Result<T, E>
   |                  -- lifetime `'b` defined here
...
44 |         Extern::something::<T, E, _>(|t| f(S::new(self, t)))
   |                                       -    ^^^^^^^^^^^^^^^
   |                                       |    |
   |                                       |    `t` escapes the closure body here
   |                                       |    argument requires that `'1` must outlive `'b`
   |                                       `t` is a reference that is only valid in the closure body
   |                                       has type `&'1 mut Extern`

Yeah, your two implementations have conflicting requirements.

TestWithTest can't have a higher-ranked implementation as described, but the implementation for Test needs one, because here:

        Extern::something::<T, E, _>(|t: &mut Extern| f(S::new(self, t)))

if S doesn't have the higher-ranked implementation, it can only work with a &'a mut Extern (due to the call to S::new), but the API of Extern requires the more general signature (t: &mut Extern).

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.