为什么在使用Option :: map时会出现借用错误,但在手动匹配时却没有出现?

时间:2019-04-28 10:42:51

标签: reference rust pattern-matching

我有这个工作功能:

fn clear_job(state: State<MyState>) -> Option<String> {
    let mut guard = state.job.lock().unwrap();
    let maybe_job: &mut Option<Job> = &mut *guard;
    // Job is not Copy nor Clone

    match maybe_job {
        None => None,
        Some(job) => match job {
            Job::InProgress { .. } => Some("Can't clear in progress job".into()),
            _ => {
                *maybe_job = None;
                Some("Job cleared".into())
            },
        },
    }
}

如果我有None,我将返回None;如果我有Some,我将返回Some,这就是Option::map()的确切含义!

我试图重写此功能:

fn clear_job(state: State<MyState>) -> Option<String> {
    let mut guard = state.job.lock().unwrap();
    let maybe_job: &mut Option<Job> = &mut *guard;

    maybe_job.as_ref().map(|job| match job {
        Job::InProgress { .. } => "Can't clear in progress job".into(),
        _ => {
            *maybe_job = None;
            "Job cleared".into()
        },
    })
}

这会给我这个错误:

error[E0500]: closure requires unique access to `maybe_job` but it is already borrowed
   --> src/main.rs:113:28
    |
113 |     maybe_job.as_ref().map(|job| match job {
    |     ---------          --- ^^^^^ closure construction occurs here
    |     |                  |
    |     |                  first borrow later used by call
    |     borrow occurs here
...
116 |             *maybe_job = None;
    |              --------- second borrow occurs due to use of `maybe_job` in closure

我有点理解为什么存在错误;我不明白的是,在match版本中我没有遇到错误,因为从语义上讲,我正在做同样的事情:读入maybe_job,借用{{1} }(据说也可以在job上使用),但仍会写入maybe_job

为什么我允许使用第一个版本而不允许第二个版本?在这种情况下是否可以使用*maybe_job

1 个答案:

答案 0 :(得分:1)

  

我有点理解为什么存在错误;我不明白的是,在match版本中我没有遇到错误,因为从语义上讲,我正在做同样的事情:读入maybe_job,借用{{1} }(据说也可以在job上使用),但仍会写入maybe_job

在匹配情况下,编译器通过在写*maybe_job之前放下job上的借位来帮助您。您可以自己进行测试-在执行*maybe_job之后使用job,您将显式借用*maybe_job = None太长时间,编译器将出错。

job情况下,作为闭包map的参数的借用是对|job|的不可变借用。从闭包中访问变量也是(堆栈中变量的)借用,因此尝试分配给maybe_job时需要对已经借入的值进行可变借用。

编译器允许一个而不允许另一个的原因仅仅是一个问题,即分析的复杂程度-自动将借用放到*maybe_job中,编译器必须检测并确保{{1} }是|job|上的唯一借项-这非常棘手。如果您进行maybe_job.as_ref()-并且maybe_job复制不可变的引用会怎样?