关闭上下文中的Rust所有权规则

时间:2014-08-27 20:46:57

标签: rust

我正在玩Rust中的新闭包,我遇到了一种情况,再次向我显示我还没有完全掌握所有权规则。

#![feature(unboxed_closures)]
#![feature(overloaded_calls)]

fn main() {
    let mut test = 5i;
    let do_something = ref |:| { println!("{}", test) };
    test = 6i;
    do_something();

    println!("{}", test);
}

此代码无法告诉我作业test = 6i;无效,因为test已经借用do_something封闭。

但是阅读所有权规则(来自Rust指南)对我来说似乎有用:

  

1.您可以控制何时释放该资源。

     

2.您可以不可避免地将该资源借给任意数量的借款人。

     

3.您可以将资源可变地借给一个借款人。 BUT

     

4.一旦你这样做了,你可能也不会以其他方式,可变或不可变的方式借出来。

     

5.如果你现在把它借给某人,你可能不会透支出来。

上面的代码有什么问题。 test是所有者,do_something应该只有不可变引用。如果我们借给某人的唯一引用是 immutable ,那么更改test的值是不合法的呢?

关注

现在我了解到所有者的访问权限也被视为贷款,我将代码更改为使用Cell

#![feature(unboxed_closures)]
#![feature(overloaded_calls)]

use std::cell::Cell;

fn main() {
    let test = Cell::new(5i);
    let do_something = ref |:| { println!("{}", test) };
    test.set(6i);
    do_something();

    println!("{}", test);
}

但我想知道为什么这会打印

5
6

而不是

6
6

我如何更改代码才能打印出来?

6
6

2 个答案:

答案 0 :(得分:2)

正如你引用自己:

  

如果您目前正在将其借给某人,您可能不会透支出来。

由于您已将test借给do_something,因此在do_something超出范围之前,您无法以可变方式访问它。

答案 1 :(得分:2)

回答你的后续行动:

这似乎是因为CellCopy,所以它被复制到闭包中。如果你这样做(现在ref在关闭之前无关紧要并且可以省略):

#![feature(unboxed_closures)]
#![feature(overloaded_calls)]

use std::cell::Cell;

fn main() {
    let test = Cell::new(5i);
    let test_ref = &test;
    let do_something = |:| { println!("{}", test_ref.get()) };
    test.set(6i);
    do_something();

    println!("{}", test.get());
}

然后打印两个6 s。

但是,我认为这种行为有些出乎意料。我当然希望带有ref前缀的闭包会通过引用将所有的环境带入其中。我刚刚为此提交了issue