Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
413 views
in Technique[技术] by (71.8m points)

rust - Implementing a trait method returning a bounded lifetime reference for owned type

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 ?

question from:https://stackoverflow.com/questions/65943869/implementing-a-trait-method-returning-a-bounded-lifetime-reference-for-owned-typ

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This isn't really possible. Trait methods can only have a single prototype, and all implementations have to match that prototype.

For the case New<&'a str>, your prototype needs to be what you have

fn as_ref(&self) -> New<&'a str>;

For the case New<String>, on the other hand, you would need

fn as_ref<'b>(&'b self) -> New<&'b str>;

instead, i.e. the lifetime of the return value needs to be tied to the lifetime of the self reference. This prototype is different, since lifetimes are part of the prototype.

Your attempt to solve this with a trait bound Self: 'a can't work. The type Self is New<String> here, which does not contain any references, so it in fact trivially fulfils Self: 'static, and thus any lifetime bound. The bound does not further constrain the Self type in any way. You can't restrict the lifetime of the self reference at the impl level, and bounding it at the function definition level will result in diverging from the prototype in the trait definition, as explained above.

For the same reason, you can't get an &'a str from a Cow<'a, str> by dereferencing. The Cow might be owned, in which case the returned reference can only live as long a the self reference used for dereferencing.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...