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()
drop x
(从注释掉的代码中的错误可以看出),但仍然认为变量是从 a
借来的!这不公平!
这应该被认为是rust-lang/rust#6393(现在由rust-lang/rfcs#811跟踪?)的众多欺骗之一 . 但是那里的讨论似乎集中在使 &mut self
和 &self
在一个块中共存 .
2 回答
我不能给你一个明确的答案,但我会在这里解释一些事情 . 让我们从澄清一些事情开始:
这不是真的 . 虽然编译器知道标准库中有一些"magic",但
drop()
并不是一个lang项目 . 事实上,你可以自己实现drop()
,这实际上是最简单的事情:该函数只是按值取值(因此,它被移入
drop()
)并且由于drop()
内部没有任何反应,因此该值在范围的末尾被删除,就像在任何其他函数中一样 . 所以:编译器不知道x
被删除了,它只知道x
被移动了 .您可能已经注意到,无论我们是否添加
drop()
调用,编译器错误都保持不变 . 现在,编译器只会在引用时查看变量的范围 . 从Niko Matsakis' intro to NLL:并在a later blog post of his:
这正是这里发生的事情,所以是的,你的问题与所有这些"lexical borrowing"的东西有关 . 从当前编译器的角度来看,表达式
&a
的生命周期必须至少与x
的范围一样大 . 但这不起作用,因为引用会比a
更长,因为x
的范围大于编译器指出的a
的范围:我猜你已经知道了这一切,但你可以通过交换
let mut x ...;
和let a ...;
来修复你的例子 .我不确定这个确切的问题是否可以通过任何目前提出的解决方案来解决 . 但我希望我们能尽快看到,因为所有这些都将作为Rust 2017路线图的一部分得到解决 . 阅读更新的好地方是here(其中还包含Niko的五篇相关博客文章的链接) .
Rust编译器对
drop
以及它的作用一无所知 . 它只是一个库函数,它可以用它的 Value 做任何事情,因为它现在拥有它 .正如文档所指出的那样,
drop
的定义实际上只是:它起作用,因为它将参数移入函数中,因此在函数完成时由编译器自动删除 .
如果您创建自己的函数,您将得到完全相同的错误消息:
这正是it says drop "isn't magic"文档中的含义 .