为什么在 "as_slice" 的情况下引用的寿命不够长?
Why does a reference not live long enough in case of "as_slice"?
我不明白为什么这段代码可以编译:
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 }
如果我理解正确,在任何一种情况下函数签名都是相同的,并且 return 值生命周期等于输入参数一。那么为什么 "as_slice" 不起作用?
这是 "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
时没有办法表达这一点(现在这个更高等级的特征界限可能是可能的)。这样做的效果是,当我们在你的函数 f
中调用 as_slice()
时,我们将返回一个新的生命周期,它无法逃脱 f
。这实际上是您遇到的错误。
如果现在编写 AsSlice
,它将使用关联类型并且能够以我们想要的方式 link 生命周期。它将类似于以下内容:
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[] }
}
这类似于 as_mut_slice 目前的实施方式(这就是它起作用的原因)
我不明白为什么这段代码可以编译:
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 }
如果我理解正确,在任何一种情况下函数签名都是相同的,并且 return 值生命周期等于输入参数一。那么为什么 "as_slice" 不起作用?
这是 "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
时没有办法表达这一点(现在这个更高等级的特征界限可能是可能的)。这样做的效果是,当我们在你的函数 f
中调用 as_slice()
时,我们将返回一个新的生命周期,它无法逃脱 f
。这实际上是您遇到的错误。
如果现在编写 AsSlice
,它将使用关联类型并且能够以我们想要的方式 link 生命周期。它将类似于以下内容:
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[] }
}
这类似于 as_mut_slice 目前的实施方式(这就是它起作用的原因)