Rust 参考在仍然借用的情况下被丢弃在这里

2023-12-19

问题:我从一个方法中收到“XXXXXXX 在仍借用时被丢弃”错误,其中 XXXXXXX 在方法结束时有效(这很好),但 Rust 不必要地期望它与输入引用一样长因为它们有明确的生命周期。

这是一些设置信息:我有一个结构,其中迭代文本内容中所有找到的查询。

pub struct QueryRangeItr<'a> {
    inverted: bool,
    query: &'a str,
    content: &'a str,
}

它获取查询和内容的引用,并期望实例的持续时间与查询/内容一样长。到目前为止,一切都很好。

impl<'a> QueryRangeItr<'a> {
    fn new(query: &'a str, content: &'a str, inverted: bool) -> QueryRangeItr<'a> {
        Self {
            inverted,
            query,
            content,
        }
    }
}

我有一个静态方法,允许您对每个找到的查询执行转换。它需要一个闭包并将其应用于查询,然后为您提供一个新的String没有生命周期依赖性。因为返回值没有生命周期,所以我实际上没有want为这里的查询和内容带来生命周期,但如果我不这样做,Rust 告诉我我需要......因此,它们有生命周期要求。就其本身而言,这工作得很好。

问题发生在另一个调用的静态方法上transform两次转换两个查询and非查询内容。它首先调用transfrom对找到的查询应用一个闭包。结果反馈到另一个调用transform方法,但这次对其余内容应用变换。

impl<'a> QueryRangeItr<'a> {
    pub fn transform<T>(
        query: &'a str,
        content: &'a str,
        transform: T,
        inverted: bool,
    ) -> String where T: Fn(&str) -> String {
        let selects = Self::new(query, content, true);
        // ...
        // returns a `String` with no lifetime dependency on input params
    }

    pub fn transform_all<TQ, TNQ>(
        query: &'a str,
        content: &'a str,
        transform_query: TQ,
        transform_non_query: TNQ,
    ) -> String
        where
            TQ: Fn(&str) -> String,
            TNQ: Fn(&str) -> String,
    {
        let transformed_content = Self::transform(query, content, &transform_query, false);
        let transformed_query = transform_query(query);
        let transformed = Self::transform(&transformed_query, &transformed_content, transform_non_query, true); // <--- Rust expects `transformed_content` and `transformed_query` to match the lifetime of `query` and `content`
        transformed
    }

}

transformed_content and transformed_query两人都在最后死去transform_all...这是有道理的,但 Rust 希望它们与输入参数一样长query and content('a)...并且不会。

I don't actually需要他们再活下去。一旦我得到transformed回来后,我不再需要它们了。然而,拥有一生query and content让 Rust 认为它们需要比实际需要的持续时间更长,我收到此错误:

115 | impl<'a> QueryRangeItr<'a> {
    |      -- lifetime `'a` defined here
...
200 |         let transformed = Self::transform(&transformed_query, &transformed_content, transform_non_query, true);
    |                           ------------------------------------^^^^^^^^^^^^^^^^^^^^----------------------------
    |                           |                                   |
    |                           |                                   borrowed value does not live long enough
    |                           argument requires that `transformed_content` is borrowed for `'a`
201 |         transformed
202 |     }
    |     - `transformed_content` dropped here while still borrowed

如果我删除生命周期,我会收到此错误:

error[E0621]: explicit lifetime required in the type of `query`
   --> src/range/query_range_iterator.rs:130:23
    |
125 |         query: &str,
    |                ---- help: add explicit lifetime `'a` to the type of `query`: `&'a str`
...
130 |         let selects = Self::new(query, content, invert);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required

而且,如果我尝试定义一个不同的生命周期'a ('b or '_)对于我的转换方法,我得到这样的结果:

error[E0521]: borrowed data escapes outside of associated function
   --> src/range/query_range_iterator.rs:130:23
    |
126 |         content: &'_ str,
    |         ------- `content` is a reference that is only valid in the associated function body
...
130 |         let selects = Self::new(query, content, invert);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `content` escapes the associated function body here

我想做的是找到一种方法向 Rust 证明我不需要transformed_content and transformed_query只要它想。

有什么想法吗?


Replace

 = Self::transform(&transformed_query, &transformed_content, ...
// ^^^^

with

 = QueryRangeItr::transform(&transformed_query, &transformed_content, ...
// ^^^^^^^^^^^^^

通过使用Self,你正在使用相同的生命周期'a对于一切。正如你所指出的,transformed_content and transformed_query只存在于函数内,所以它们的生命周期肯定更短并且无法匹配'a。更换Self with QueryRangeItr允许编译器选择新的生命周期'a来电。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rust 参考在仍然借用的情况下被丢弃在这里 的相关文章

随机推荐