Let's assume I have this struct and this trait:
#[derive(Debug)]
pub struct New<T>(T);
pub trait AsRefNew<'a> {
fn as_ref(&self) -> New<&'a str>;
}
That is, the AsRefNew
trait allows to return a reference with a given lifetime 'a
wrapped in a New
newtype. This lifetime 'a
may be different (and will be) from the lifetime of the &self
parameter.
Now I can implement this trait for a New(&str)
, and make it so that the lifetime of the output is the lifetime of the wrapped &str
:
impl<'a> AsRefNew<'a> for New<&'a str> {
fn as_ref(&self) -> New<&'a str>{
New(self.0)
}
}
My problem is that I would like to implement the trait for New(String)
, and this time, I would like 'a
to actually match the lifetime of self
. My understanding is that something like that should work:
impl<'a> AsRefNew<'a> for New<String> where Self: 'a{
fn as_ref(&self) -> New<&'a str> {
New(self.0.as_str())
}
}
Except it does not:
error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
--> src/main.rs:16:20
|
16 | New(self.0.as_str())
| ^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 15:5...
--> src/main.rs:15:5
|
15 | fn as_ref(&self) -> New<&'a str> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:16:13
|
16 | New(self.0.as_str())
| ^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 14:6...
--> src/main.rs:14:6
|
14 | impl<'a> AsRefNew<'a> for New<String> where Self: 'a{
| ^^
note: ...so that the expression is assignable
--> src/main.rs:16:9
|
16 | New(self.0.as_str())
| ^^^^^^^^^^^^^^^^^^^^
= note: expected `New<&'a str>`
found `New<&str>`
I tried different variations of lifetimes and generic, but I can not find a better way to express the fact that I, in this case, want 'a
to match '_
.
The goal is to have this snippet to work:
fn main() {
// This works:
let a = String::from("Hey");
let b;
{
let c = New(a.as_str());
b = c.as_ref().0;
}
println!("{:?}", b);
// I would like that to work as well:
let a = String::from("Ho");
let b;
let c = New(a);
{
b = c.as_ref().0;
}
println!("{:?}", b);
}
Any ideas ?
'a
may be different (and will be) from the lifetime of the&self
parameter" with some concrete examples. Please edit your question to update it with additional clarifying details. Given your question as-is I was able to come up with this example but I'm not sure if it actually solves your problem. – pretzelhammerNew<String>
, and not forNew<&String>
. – Alex Péré