不能借用为不可变的,因为在验证闭包被调用时它也被借用为可变的

Cannot borrow as immutable because it is also borrowed as mutable when verifing that a closure was called

我有一个函数需要一个闭包来执行与输出相关的逻辑(例如显示到标准输出):

fn handle(mut output: impl FnMut(String) -> ()) -> Result<(), String> {
    // do something that produces output string `message`
    let message = "example".to_string();
    Ok(output(message))
}

我正在尝试为此函数编写一个集成测试,我在其中定义了一个存根输出函数,它将输出字符串保存到本地可变变量中:

#[test]
fn should_work() {
    let mut output_message = String::from("");
    let output = |message: String| {
        output_message = message;
    };

    let result = handle(output);

    assert!(result.is_ok());
    assert_eq!("blah", output_message);
}

但是我有错误:

error[E0502]: cannot borrow `output_message` as immutable because it is also borrowed as mutable
  --> src/lib.rs:18:24
   |
11 |     let output = |message: String| {
   |                  ----------------- mutable borrow occurs here
12 |         output_message = message;
   |         -------------- previous borrow occurs due to use of `output_message` in closure
...
18 |     assert_eq!("blah", output_message);
   |                        ^^^^^^^^^^^^^^ immutable borrow occurs here
19 | }
   | - mutable borrow ends here

有什么方法可以使用这种方法进行测试吗?我简单地搜索了一些模拟板条箱,但所有的板条箱似乎都没有经常更新,而且它们对我的场景来说有点过分了。

如果没有,是否有更好的替代方法来测试此功能?

您可以将匿名函数放在本地范围内,以便在您断言时删除它:

#[test]
fn should_work() {
    let mut output_message = String::from("");

    let result = {
        let output = |message: String| {
            output_message = message;
        };

        handle(output)
    };

    assert!(result.is_ok());
    assert_eq!("blah", output_message);
}

内联闭包:

#[test]
fn should_work() {
    let mut output_message = String::from("");

    let result = handle(|message| {
        output_message = message;
    });

    assert!(result.is_ok());
    assert_eq!("blah", output_message);
}

这样,闭包是临时的,不会长期借用价值。作为奖励,您可以避免在闭包参数上指定类型。

或者等待几周直到 Rust 1.31 并打开 Rust 2018 模式,其中有 non-lexical lifetimes