Inferred bounds incompatible with explicit bounds

trait GetX {
    type X;
    
    fn get_x<'a> (self: &'a Self) -> &'a Self::X;
}

pub
struct Foo {
    x: i32,
}

impl GetX for Foo {
    type X = i32;

    fn get_x<'a> (self: &'a Self) -> &'a Self::X
    where
        Self     : 'a,
        Self::X  : 'a,
    {
        &self.x
    }
}

gives

error[E0195]: lifetime parameters or bounds on method `get_x` do not match the trait declaration
  --> src/lib.rs:15:13
   |
4  |     fn get_x<'a> (self: &'a Self) -> &'a Self::X;
   |             ---- lifetimes in impl do not match this method in trait
...
15 |     fn get_x<'a> (self: &'a Self) -> &'a Self::X
   |             ^^^^ lifetimes do not match method in trait

Is this a bug or is there some thing I am missing? From my understanding since Self : 'a is a necessary bound for the &'a Self type to even exist (ditto for &'a Self::X), these two function signatures should be equivalent.

Here is my code:

trait GetX {
    type X;
    
    fn get_x<'a> (self: &'a Self) -> &'a Self::X;
}

pub
struct Foo {
    x: i32,
}

impl<'a> GetX for Foo {
    type X = i32;

    fn get_x<'b> (self: &'b Self) -> &'b Self::X
     where
         Self     : 'a,
         Self::X  : 'a,
    {
        &self.x
    }
}

fn main() {

}

Refer to E0496

@lfwelove That's not the issue, @Yandros is not asking to fix the code, he's asking why Rust complains for something that looks valid.

@Yandros I think the issue is that Rust does a very simple check to see if function impl conforms to the trait definition. So it doesn't do any deep lifetime analysis to validate that the two functions are the same.

1 Like

I told him why, you missed my point

You're code is different from his, he only has lifetimes on the function get_x itself, nowhere else. Your code has 'a at the impl block, which has different semantics from his. Also the bounds you gave are different, so it doesn't apply to his question. Finally, he got error code E0195, not E0496.

So what's your solution? I'm interested in this topic. pls make his code works :smile:

To make this work just remove the extraneous bounds.

impl GetX for Foo {
    type X = i32;

    fn get_x(self: &Self) -> &Self::X
    {
        &self.x
    }
}

But it is weird that this signature

fn get_x(self: &Self) -> &Self::X where Self: 'a, Self::X: 'a

does not work. I think this is what @Yandros is getting at.

1 Like

That's what I suspected :confused: ; I was working on a proc-macro applied to impl blocks that required using the second form, and obviously the method in the trait had the usual simpler signature. I guess I will have to make the proc-macro add the Self : 'a bounds itself :woman_shrugging: