为什么引用不能在“as_slice”的情况下活得足够长?

时间:2015-01-27 16:49:24

标签: rust

我无法弄清楚为什么这段代码会编译:

fn f(v: &mut Vec<isize>) -> &[isize] {
    v.as_mut_slice()
}

而这不是:

fn f(v: &mut Vec<isize>) -> &[isize] {
    v.as_slice()
}
制造

<anon>:2:5: 2:6 error: `v` does not live long enough
<anon>:2     v.as_slice()
             ^
<anon>:1:38: 3:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 1:37...
<anon>:1 fn f(v: &mut Vec<isize>) -> &[isize] {
<anon>:2     v.as_slice()
<anon>:3 }
<anon>:1:38: 3:2 note: ...but borrowed value is only valid for the block at 1:37
<anon>:1 fn f(v: &mut Vec<isize>) -> &[isize] {
<anon>:2     v.as_slice()
<anon>:3 }

如果我理解正确,在任何一种情况下,函数签名都是相同的,并且返回值的生命周期等于输入参数1。那么为什么&#34; as_slice&#34;不起作用?

1 个答案:

答案 0 :(得分:2)

这是“bug”或更好的AsSlice特质的限制。由于v.as_slice()现在不稳定,可能会被删除而转而使用&v[](已经按照预期的方式工作)我不会打开错误,但我会尝试解释当前特征的原因不尽我所知。

首先,查看您案例中调用的definition of the as_slice

impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a mut U {
    #[inline(always)]
    fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
}

请注意,as_slice实际上已经过了新的生命周期。如果我们给它起一个名字('b),我们实际上写的是:

impl<'a, T, U: ?Sized + AsSlice<T>> AsSlice<T> for &'a mut U {
    #[inline(always)]
    fn as_slice<'b>(&'b self) -> &'b [T] { AsSlice::as_slice(*self) }
}

我们真正想要的是'b'a相同,但我认为在创建AsSlice时无法表达这一点(现在可能是可能具有较高的排名特征界限)。这样做的结果是,当我们在您的函数as_slice()中调用f时,我们将返回一个无法逃避f的新生命周期。这实际上是你得到的错误。

如果现在编写AsSlice,它将使用关联类型,并能够以我们想要的方式链接生命周期。这将是类似的事情:

pub trait AsSlice2 {
    type Item;
    fn as_slice_2(&self) -> & [Self::Item];
}

impl<T> AsSlice2 for [T] {
    type Item = T;
    fn as_slice_2(&self) -> &[T] { &self[] }
}

playpen

这类似于当前实现的as_mut_slice(这就是为什么有效)