What is the point of an explicit lifetime for a method that doesn't take any arguments?

怎甘沉沦 提交于 2019-12-11 07:58:54

问题


On page 295 of Programming Rust you can find the following:

Fortunately, the standard library includes the blanket implementation:

impl<'a, T, U> AsRef<U> for &'a T
where
    T: AsRef<U>,
    T: ?Sized,
    U: ?Sized,
{
    fn as_ref(&self) -> &U {
        (*self).as_ref()
    }
}

I'm confused at the use of &'a there. What is the context of that? It's not being used in an argument of as_ref nor tied to the output of &U. I don't think I fully understand lifetimes when used in this context.

I looked this up because I still didn't understand it and the answers still weren't clicking (making sense). I found convert.rs. This doesn't seem to have any lifetimes anywhere, but it implements the AsRef trait. So why does the book have this, and not the actual code in Rust? Where can I find the "blanket implementation" mentioned in the book?


回答1:


It's not being used in an argument of as_ref

It most certainly is. The function uses a shorthand notation, which can be expanded:

fn as_ref(&self) // becomes
fn as_ref(self: &Self) // becomes
fn as_ref(self: &&'a T)

nor tied to the output of &U

Correct.

So why does the book have this, and not the actual code in Rust?

Rust releases new stable versions every 6 weeks. Presumably the book does not, so it is likely that they are using an older version of Rust. Hopefully the book tells you the version they developed with.

As E_net4 already stated, the requirement to specify the 'a in this case was removed in Rust 1.31, as documented in the edition guide.

The code you provide from the book matches that found in Rust 1.30:

impl<'a, T: ?Sized, U: ?Sized> AsRef<U> for &'a T where T: AsRef<U>
{
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

The source code you looked at corresponds to Rust 1.37:

impl<T: ?Sized, U: ?Sized> AsRef<U> for &T where T: AsRef<U>
{
    fn as_ref(&self) -> &U {
        <T as AsRef<U>>::as_ref(*self)
    }
}

This is about 42 weeks of development time, plenty for the source code to have changed.




回答2:


References are always generic to a lifetime. In practice, a &T is always a &'a T for some lifetime established by the compiler according to the given circumstances. This lifetime has to be specified in some way when implementing something for a reference type.

There used to be a time when there was no possibility for lifetime elision in implementation statements. This changed in version 1.31 of the compiler, but there was no need to change all existing, working code because of this. The code below works today, but not in version 1.30.0:

trait Foo {
    fn foo(&self) {}
}

impl<T: ?Sized> Foo for &T {} // error[E0106]: missing lifetime specifier

As such, the lifetime parameter 'a was made explicit in this case. The only way it relates from the lifetimes in &self and &U is that there will be covariance with 'a: since self = &'a T is bound to the lifetime 'a, it is also implicit that &self must not outlive the lifetime 'a.



来源:https://stackoverflow.com/questions/58030348/what-is-the-point-of-an-explicit-lifetime-for-a-method-that-doesnt-take-any-arg

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!