【问题标题】:Borrowed value does not live long enough for `AsRef` result even if its `self` lives long enough借来的值对于“AsRef”结果的寿命不够长,即使它的“自我”寿命足够长
【发布时间】:2018-11-22 20:35:44
【问题描述】:

我有一个将一些功能包装在切片周围的结构:

use std::fmt::Debug;

struct SliceWrapper<'a, T: Debug + Copy + 'a> {
    slice: &'a [T],
    pos: usize,
}

我想为每个支持 AsRef&lt;T: Debug + Copy + 'a&gt; 的元素实现 From 特征,如下所示:

impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
    fn from(slice: R) -> Self {
        Self {
            slice: slice.as_ref(),
            pos: 0,
        }
    }
}

我得到错误:

error[E0597]: `slice` does not live long enough
  --> src/lib.rs:11:20
   |
11 |             slice: slice.as_ref(),
   |                    ^^^^^ borrowed value does not live long enough
...
14 |     }
   |     - borrowed value only lives until here
   |
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 8:6...
  --> src/lib.rs:8:6
   |
8  | impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
   |      ^^

我不明白这一点,因为我说R (slice) 必须和我的SliceWrapper 一样长——据我了解,AsRef&lt;_&gt; 继承了它的生命周期 self (slice)...

【问题讨论】:

    标签: generics rust traits lifetime


    【解决方案1】:

    nightly 的完整错误消息非常清楚地说明了这里发生的情况。你将slice 移动到函数from() 中,然后使用as_ref() 借用它,然后它在作用域的末尾被删除:

    8  | impl<'a, T: Debug + Copy + 'a, R: AsRef<[T]> + 'a> From<R> for SliceWrapper<'a, T> {
       |      -- lifetime `'a` defined here
    9  |     fn from(slice: R) -> Self {
    10 |         Self{ slice: slice.as_ref(), pos: 0 }
       |                      ^^^^^---------
       |                      |
       |                      borrowed value does not live long enough
       |                      argument requires that `slice` is borrowed for `'a`
    11 |     }
       |     - `slice` dropped here while still borrowed
    

    您正在尝试创建一个可以终生使用的借用 'a,但您从中借用的所有者 slice 的寿命不够长。

    From 特征似乎不适合这个用例。该特征的想法是将某些数据的所有权转移到新类型,但您的 SliceWrapper 不拥有所有权。我建议编写一个自定义构造函数,而不是通过引用获取R

    【讨论】:

    • 啊该死,因为R(和它的切片)在from 返回时被删除,而SliceWrapper 应该在之后继续存在......?
    • 这个错误对于 nightly 来说并不特殊; Rust 1.30 有完全相同的。
    • 是的;问题信息很清楚——我只是没明白。遗传学有时让我感到困惑?
    【解决方案2】:

    您可以将转换限制为引用参数,然后您有一个很好的方式来表达您需要的借用——生命周期取自输入引用:

    impl<'a, T, R> From<&'a R> for SliceWrapper<'a, T>
    where
        T: Debug + Copy + 'a,
        R: AsRef<[T]>
    {
        fn from(slice: &'a R) -> Self {
            Self {
                slice: slice.as_ref(),
                pos: 0,
            }
        }
    }
    

    现在你可以按照你原来的推理。 你有 AsRef 给你:&amp;'x self -&gt; &amp;'x [T] 任何'x,你输入一个&amp;'a R,所以你得到一个&amp;'a [T]

    引用From 有时存在,我认为它特别适合于引用到引用的转换。 std 中的一个例子是impl&lt;'a&gt; From&lt;&amp;'a str&gt; for Cow&lt;'a, str&gt;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-26
      • 1970-01-01
      • 2015-02-28
      • 2020-01-07
      • 1970-01-01
      • 2020-12-17
      相关资源
      最近更新 更多