【问题标题】:Cannot borrow as immutable because it is also borrowed as mutable when verifing that a closure was called不能作为不可变借用,因为在验证闭包被调用时它也被作为可变借用
【发布时间】:2018-11-15 23:43:32
【问题描述】:

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

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

有什么方法可以使用这种方法进行测试吗?我简单地搜索了一些模拟板条箱,但所有板条箱似乎都不会经常更新,无论如何它们对于我的场景来说有点矫枉过正。

如果没有,有什么更好的替代方法来测试这个功能?

【问题讨论】:

标签: testing rust integration-testing


【解决方案1】:

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

#[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);
}

【讨论】:

    【解决方案2】:

    内联闭包:

    #[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

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多