使用引用作为参数来更正Into <foo>的生命周期

时间:2017-03-28 14:46:08

标签: rust lifetime

我不确定这里要问的问题是什么,但我在使用通用方法设置正确的生命周期时遇到了问题。完整的代码是here,但基本的问题是我有一个类似于下面的方法,但是我得到了一个终身错误。 &params引用中的任何内容都不会嵌入到.into()返回的结构中,因此这应该是安全的。我需要什么才能让它发挥作用?

pub fn index<'a, T, R, P>(repository: T, query: &'a str) -> Result<Vec<<R as ToJson>::Attrs>, QueryStringParseError>
    where
        T: JsonApiRepository<'a, T = R>,
        P: 'a,
        R: ToJson,
        R: QueryString<'a, Params = P>,
        <R as ToJson>::Attrs: From<(R, &'a P)>,
        QueryStringParseError: From<<T as JsonApiRepository<'a>>::Error>
{
    let params = <R as QueryString>::from_str(query)?;
    let list = repository.find_all(&params)?;

    // What's the correct lifetime incantation for this to work?
    // No references will be embedded in `R::Attrs`, so this
    // should be safe
    let data: Vec<<R as ToJson>::Attrs> = list.into_iter().map(|e| (e, &params).into()).collect();
    Ok(data)
}

(修正后的问题,错误如下)

rustc 1.16.0 (30cf806ef 2017-03-10)
error[E0373]: closure may outlive the current function, but it borrows `params`, which is owned by the current function
  --> <anon>:16:64
   |
16 |     let data: Vec<<R as ToJson>::Attrs> = list.into_iter().map(|e| (e, &params).into()).collect();
   |                                                                ^^^      ------ `params` is borrowed here
   |                                                                |
   |                                                                may outlive borrowed value `params`
   |
help: to force the closure to take ownership of `params` (and any other referenced variables), use the `move` keyword, as shown:
   |     let data: Vec<<R as ToJson>::Attrs> = list.into_iter().map(move |e| (e, &params).into()).collect();

1 个答案:

答案 0 :(得分:2)

你得到的错误(我不知道你为什么不分享):

error[E0373]: closure may outlive the current function, but it borrows `params`, which is owned by the current function
  --> src/main.rs:22:64
   |
22 |     let data: Vec<<R as ToJson>::Attrs> = list.into_iter().map(|e| (e, &params).into()).collect();
   |                                                                ^^^      ------ `params` is borrowed here
   |                                                                |
   |                                                                may outlive borrowed value `params`
   |
help: to force the closure to take ownership of `params` (and any other referenced variables), use the `move` keyword, as shown:
   |     let data: Vec<<R as ToJson>::Attrs> = list.into_iter().map(move |e| (e, &params).into()).collect();

您在函数内部创建params,但是所有特征边界都要求params的生命周期必须与从外部传入的字符串的生命周期相匹配。它不可能满足那个界限,看起来params的引用必须比函数更长寿,通过闭包。因此马马虎虎的错误信息。

你不应该将这些生命期结合在一起。请改用higher-ranked trait bounds

pub fn index<T, R, P, S, F>
    (repository: T,
     query: &str)
     -> Result<JsonApiArray<<R as ToJson>::Attrs>, QueryStringParseError>
    where T: JsonApiRepository<T = R>,
          P: Params,
          P: Default,
          P: TypedParams<SortField = S, FilterField = F>,
          P: for<'b> TryFrom<(&'b str, SortOrder, P), Err = QueryStringParseError>,
          P: for<'b> TryFrom<(&'b str, Vec<&'b str>, P), Err = QueryStringParseError>,
          R: ToJson,
          R: for<'b> QueryString<'b, Params = P, SortField = S, FilterField = F>,
          R: JsonApiResource<Params = P>,
          <R as ToJson>::Attrs: for<'b> From<(R, &'b P)>,
          QueryStringParseError: From<<T as JsonApiRepository>::Error>
{