首页 > 解决方案 > 为什么闭包的可变引用参数不会超过函数调用?

问题描述

我正在使用cssparsercrate 来解析一些 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<'_>>`

正如在这个答案中所读,我添加了我的闭包的返回类型:

    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")
    };

标签: rustlifetime

解决方案


不幸的是,闭包不能声明生命周期参数,这将需要传达此函数的正确生命周期。将其移出函数会产生更好的错误:

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>,因此它不知道应该推导出&'_ str什么生命周期。BasicParseError<'_>

查看 的签名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")
}

推荐阅读