移动变量调用`drop`后,仍然借用?移动变量调用`drop`后,仍然借用?(Moved varia

2019-05-12 10:57发布

fn main() {
    let mut x: Vec<&i32> = vec![];
    let a = 1;
    x.push(&a);
    drop(x);
    // x.len(); // error[E0382]: use of moved value: `x`
}  // `a` dropped here while still borrowed

编译器知道drop()下降x (在注释掉的代码显而易见的错误),但仍然认为变量是从借用a ! 这不公平!

如果这被认为是众多受骗者之一防锈琅/防锈#6393 (目前已被跟踪防锈琅/ RFC文档#811但讨论?)似乎有上做出为中心&mut self&self在一个共存块。

Answer 1:

我不能给你一个明确的答案,但我会尝试在这里解释一些事情。 让我们开始与澄清的东西:

编译器知道drop()下降x

这不是真的。 虽然在编译器知道,标准库的几个“神奇”的东西drop()是没有这样的郎项 。 事实上,你可以实现drop()自己,它实际上是最容易做的事情:

fn drop<T>(_: T) {}

该功能只需要通过一些有价值的东西(因此,它搬进drop()并因为没有内部发生drop()这个值在范围月底在其它任何功能下降,等等。 所以说:编译器不知道x被丢弃,它只知道x移动。


正如你可能已经注意到,该编译器错误,无论我们是否添加保持不变drop()调用。 眼下,编译器将只能看一个变量的范围 ,当涉及到的引用。 从尼科Matsakis'介绍到NLL :

编译器当前工作,分配参考为一个可变的方式意味着它的寿命必须是该变量的整个范围一样大。

而在他的后面的博客文章 :

特别是今天,当了一辈子必须超越单个语句的界限[...],它必须扩展,直到封闭块结束时,所有的方式。

这是在这里究竟发生了什么,所以是的,你的问题与这一切“词汇借”东西做。 从目前的编译器的角度来看,该表达式的寿命&a需要是至少为的范围一样大x 。 但是,这并不工作,因为引用的将活得比a ,因为范围x比范围更大的a由编译器指出:

= note: values in a scope are dropped in the opposite order they are created

我猜你已经知道了这一切,但是你可以通过交换线路解决您的例子let mut x ...;let a ...;


我不知道这是否准确的问题,将通过目前任何提议的解决方案来解决。 但我希望,我们将看到很快就好了,因为所有这一切都被作为防锈2017年路线图的一部分解决。 对更新读了一个不好的地方就是这里 (其中还包含指向尼科的五个相关博客文章)。



Answer 2:

编译器知道drop()x (在注释的代码作为明显从误差)

锈病编译器不知道任何有关drop和它做什么。 这只是一个库函数,它可以做任何它喜欢和值,因为它现在拥有它。

的定义drop ,如文档指出,是从字面上只是:

fn drop<T>(_x: T) { }

它的工作原理,因为它的参数被移入功能,因此由编译器自动当函数结束下降。

如果你创建自己的功能,你会得到完全相同的错误信息:

fn my_drop<T>(_x: T) { }

fn main() {
    let mut x: Vec<&i32> = vec![];
    let a = 1;
    x.push(&a);
    my_drop(x);
    x.len();
}

这正是在文档中的意思时, 它说drop “是不是魔术” 。



文章来源: Moved variable still borrowing after calling `drop`?
标签: rust lifetime