NB: I tried to keep this post as concise as possible, the full code can be found at https://github.com/pchampin/pair_trait.
The problem
I have defined the following trait:
pub trait Pair {
type Item: Borrow<str>;
fn first(&self) -> &Self::Item;
fn second(&self) -> &Self::Item;
}
I have generic implementations of this trait for (T,T)
and [T;2]
for any T implementing Borrow<str>
.
I also have a type, built with the rental crate, containing a String
and two Cow<str>
that borrow from that string:
#[rental(covariant)]
pub struct SelfSustainedPair {
line: String,
pair: (Cow<'line, str>, Cow<'line, str>),
}
I would like this type to implement the Pair
trait above, but I can't find a way to do it.
Attempt #0
impl SelfSustainedPair {
pub fn first(&self) -> &Cow<str> { self.suffix().first() }
pub fn second(&self) -> &Cow<str> { self.suffix().second() }
}
I know that this is not an implementation of the trait,
but I just wanted to be sure that I could implement the methods first
and second
. The answer is yes: the code above compiles.
Attempt #1
impl Pair for SelfSustainedPair {
type Item = Cow<str>;
fn first(&self) -> &Cow<str> { self.suffix().first() }
fn second(&self) -> &Cow<str> { self.suffix().second() }
}
This fails to compile, with the message "expected lifetime parameter" for the 2nd line.
This is frustrating because it is so close to attempt #0 above.
Attempt #2
impl<'a> Pair for SelfSustainedPair {
type Item = Cow<'a, str>;
fn first(&self) -> &Cow<'a, str> { self.suffix().first() }
fn second(&self) -> &Cow<'a, str> { self.suffix().second() }
}
Here the compiler is complaining about an "unconstrainted lifetime parameter" for the first line (impl<'a>
).
Attempt #3
I modified my trait Pair
so that it expects a lifetime parameter. Surprisingly, this works, even if the liferime parameter is never used in the definition of the trait...
I then wrote:
impl<'a> Pair<'a> for SelfSustainedPair {
type Item = Cow<'a, str>;
fn first(&self) -> &Cow<'a, str> { self.suffix().first() }
fn second(&self) -> &Cow<'a, str> { self.suffix().second() }
}
Now the compiler complains that it "cannot infer an appropriate lifetime for autoref" in both methods...
Anyway, my intuition is that this is not the right path: the lifetime for which the returned Cow
can not be specified independantly of that of self
...
Attempt #4
Ideally, this is what I would like to write:
impl Pair for SelfSustainedPair {
type Item = Cow<'self, str>;
fn first(&self) -> &Cow<str> { self.suffix().first() }
fn second(&self) -> &Cow<str> { self.suffix().second() }
}
but obviously, the compiler doesn't know about the self
lifetime.