rust - 为什么闭包的可变引用参数不会比函数调用更长久?

标签 rust lifetime

我正在使用 cssparser crate 来解析一些 CSS 代码。我想创建一个能够解析 type 函数的闭包。作为第一步,我创建了一个非常简单的代码:

use cssparser::{Parser, ParserInput};

fn main() {
    let input_string = "type(\"image/png\")";
    let mut parser_input = ParserInput::new(input_string);
    let mut parser = Parser::new(&mut parser_input);

    let parse_type = |p: &mut Parser| {
        p.expect_function_matching("type")?;
        Ok("OK")
    };

    let res = parse_type(&mut parser);
}

我收到以下错误:

error[E0282]: type annotations needed for the closure `fn(&mut Parser<'_, '_>) -> std::result::Result<&str, _>`
 --> src/main.rs:9:43
  |
9 |         p.expect_function_matching("type")?;
  |                                           ^ cannot infer type of error for `?` operator
  |
  = note: `?` implicitly converts the error value into a type implementing `From<BasicParseError<'_>>`

如本文所述 answer ,我添加了闭包的返回类型:

    let parse_type = |p: &mut Parser| -> Result<&str, cssparser::BasicParseError> {
        p.expect_function_matching("type")?;
        Ok("OK")
    };

我仍然有一个我不明白的错误:

error: lifetime may not live long enough
 --> src/main.rs:9:9
  |
8 |     let parse_type = |p: &mut Parser| -> Result<&str, cssparser::BasicParseError> {
  |                       -                  ---------------------------------------- return type of closure is std::result::Result<&str, BasicParseError<'2>>
  |                       |
  |                       has type `&mut Parser<'1, '_>`
9 |         p.expect_function_matching("type")?;
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2`

显然'1是在'2之前发布的。我的闭包的参数是引用怎么会这样呢?在调用我的关闭之后它应该仍然存在,对吗?

我尝试显式注释对象的生命周期,但无法找到正确的方法;我总是遇到“未声明的生命周期”错误。例如:

    let parse_type = |p: &mut Parser<'i, '_>| -> Result<&str, cssparser::BasicParseError<'i>> {
        p.expect_function_matching("type")?;
        Ok("OK")
    };

最佳答案

不幸的是,closures can't declare lifetime arguments ,这将需要传达该函数的正确生命周期。将其移出到函数中会产生更好的错误:

use cssparser::{Parser, ParserInput};

fn parse_type(p: &mut Parser) -> Result<&str, cssparser::BasicParseError> {
    p.expect_function_matching("type")?;
    Ok("OK")
}

fn main() {
    let input_string = "type(\"image/png\")";
    let mut parser_input = ParserInput::new(input_string);
    let mut parser = Parser::new(&mut parser_input);

    let res = parse_type(&mut parser);
}
error[E0106]: missing lifetime specifier
 --> src\main.rs:3:41
  |
3 | fn parse_type(p: &mut Parser) -> Result<&str, cssparser::BasicParseError> {
  |                  -----------            ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say which one of `p`'s 3 lifetimes it is borrowed from
help: consider introducing a named lifetime parameter
  |
3 | fn parse_type<'a>(p: &'a mut Parser) -> Result<&'a str, cssparser::BasicParseError> {
  |              ^^^^    ^^^^^^^^^^^^^^            ^^^

error[E0106]: missing lifetime specifier
 --> src\main.rs:3:58
  |
3 | fn parse_type(p: &mut Parser) -> Result<&str, cssparser::BasicParseError> {
  |                  -----------                             ^^^^^^^^^^^^^^^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value, but the signature does not say which one of `p`'s 3 lifetimes it is borrowed from
help: consider introducing a named lifetime parameter
  |
3 | fn parse_type<'a>(p: &'a mut Parser) -> Result<&str, cssparser::BasicParseError<'a>> {
  |              ^^^^    ^^^^^^^^^^^^^^                             ^^^^^^^^^^^^^^^^^^^

编译器将尝试尽可能自动推断生命周期,但是p有三个生命周期&'1 Parser<'2, '3>涉及,所以它不知道什么生命周期&'_ strBasicParseError<'_>应该可以推导出来。

查看 Parser::expect_function_matching 的签名,您可能想要:

fn parse_type<'i>(p: &mut Parser<'i, '_>) -> Result<&'i str, cssparser::BasicParseError<'i>> {
    p.expect_function_matching("type")?;
    Ok("OK")
}

关于rust - 为什么闭包的可变引用参数不会比函数调用更长久?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66445015/

相关文章:

rust - 我可以使用单个 Cargo.toml 指定存储库结构,但可以使用多个版本的代码,每个版本都有单独的 main.rs 文件吗?

rust - 如何打印原始指针的大小?

rust - 如何从引用结构的方法返回盒装闭包?

rust - 在 S<T> 上使用通用特征强制我让 T 比 S 长寿

rust - 如何在Rust中为返回的元组设置静态生存期?

rust - 为什么不能在同一结构中存储值和对该值的引用?

rust - 装饰器模式和不可变引用

rust - 插入式编译器替换找不到 std crate

rust - 使用具有生命周期参数的关联类型特征的生命周期错误

c++ - 如何处理返回指针的生命周期?