Cows and Lifetime Parameters


#1

(Similar but not identical to this question: Return and use Self from trait with concrete lifetime).

My basic question is how can I borrow an object with a specified lifetime (parameter) for the borrow?

More practically, I want to get the following example to compile:

use std::borrow::{Cow, Borrow};
use std::borrow::Cow::{Owned, Borrowed};

trait Thingy {
    fn sum_bak(&self, &Self) -> Self;
}

#[derive(Clone)]
struct Foo(pub usize, pub String);

struct Bar<'a> {
    baz: Cow<'a,Foo>,
    bak: usize,
}

impl<'a> Bar<'a> {
    pub fn new(u: &'a Foo, n: usize) -> Bar<'a> {
        Bar { baz: Borrowed(u), bak: n }
    }
}

impl<'a> Thingy for Bar<'a> {
    fn sum_bak(&self, other: &Bar<'a>) -> Bar<'a> {
        Bar::new(self.baz.borrow(),self.bak+other.bak)
    }
}

In this form the compiler tells me that self.baz.borrow() can’t infer a lifetime due to conflicting requirements. If I change the return type of the method to Bar then it tells me that the method isn’t returning the appropriate type to implement Thingy. I think I understand both errors, but I don’t see a way to actually accomplish what I’m trying to here. Can anybody help?


#2
fn sum_bak(&self, other: &Bar<'a>) -> Bar<'a> {

is sugar (lifetime elision) for

fn sum_bak<'x, 'y>(&'x self, other: &'y Bar<'a>) -> Bar<'a> {

So self is borrowed for some time 'x but it’s not tied to the return type in any way so the compiler would not have a way to require that 'x outlives the returned value, which borrows from it.

If you want to borrow self for 'a you put &'a self in the signature. It won’t be compatible with that trait though, the trait would have to carry a parameter too:

trait Thingy<'a> {
    fn sum_bak(&'a self, &Self) -> Self;
}

impl<'a> Thingy<'a> for Bar<'a> {

Borrowing any Qux<'a> for the whole 'a in a method is usually too limiting so you might not find this solution useful and change the design or turn to the dark side unsafe.