0

I posted a similar question (Rust lifetime error expected concrete lifetime but found bound lifetime) last night, but still can't figure out how to apply it to this case now. Once again, a simplified example bellow:

struct Ref;

struct Container<'a> {
  r : &'a Ref
}

struct ContainerB<'a> {
  c : Container<'a>
}

trait ToC {
  fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> Self;
}

impl<'b> ToC for ContainerB<'b> {
  fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
    ContainerB{c:c}
  }
}

With the error message:

test.rs:16:3: 18:4 error: method `from_c` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter 'a
test.rs:16   fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
test.rs:17     ContainerB{c:c}
test.rs:18   }
test.rs:16:67: 18:4 note: expected concrete lifetime is the lifetime 'b as defined on the block at 16:66
test.rs:16   fn from_c<'a>(r : &'a Ref, c : Container<'a>) -> ContainerB<'a> {
test.rs:17     ContainerB{c:c}
test.rs:18   }
error: aborting due to previous error

What I think needs to happen is I need some way to equate / sub-type lifetime 'a, and lifetime 'b. Unlike the previous example there is no &self to use. I am guessing I can do this by adding a lifetime type argument to my trait(trait ToC<'a> ...), but I would prefer not to do this as it adds extra <'a> everywhere I want to use the trait as a type bound.

If anybody is curious(AKA can ignore this) where this might actually come up, I am using it in a library to convert between rust and python types. The trait is here. Everything works fine, but I am trying to implement a wrapper around the PyObject type (such as a numpy ndarray) and be able to convert it to and from a PyObject with this.

Thanks again!

Community
  • 1
  • 1
luke
  • 1,024
  • 3
  • 11
  • 21

1 Answers1

1

This boils down to much the same problem as in your previous question.

Self refers to the type you are implementing the trait for. In this case it is ContainerB<'b>, and so the whole thing about its not being the same applies; this time this time there is nothing to tie 'b and 'a together, either; the lifetimes are and must be assumed by the compiler to be potentially disjoint. (This is as distinct to the &'a ContainerB<'b> which guaranteed 'b ≥ 'a.)

Once you are using a lifetime defined on the method, tying that in with a lifetime on Self is not possible. The solution that is probably best is to shift the lifetime parameter from the method onto the trait:

trait ToC<'a> {
    fn from_c(r: &'a Ref, c: Container<'a>) -> Self;
}

impl<'a> ToC<'a> for ContainerB<'a> {
    fn from_c(r: &'a Ref, c: Container<'a>) -> ContainerB<'a> {
        ContainerB { c: c }
    }
}
Chris Morgan
  • 86,207
  • 24
  • 208
  • 215