调用`drop`后移动的变量仍然借用吗? [英] Moved variable still borrowing after calling `drop`?

查看:13
本文介绍了调用`drop`后移动的变量仍然借用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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 借用的!这不公平!

The compiler knows drop() drops x (as evident from the error in the commented-out code) but still thinks the variable is borrowing from a! This is unfair!

这是否应该被视为 rust-lang/rust#6393 的众多欺骗之一(现在由 rust-lang/rfcs#811?) 但那里的讨论似乎集中在使 &mut self&self 共存于一个块上.

Should this be considered as one of numerous dupes of rust-lang/rust#6393 (which is now tracked by rust-lang/rfcs#811?) But the discussion there seems to be centered on making &mut self and &self coexist in a single block.

推荐答案

我不能给你一个明确的答案,但我会在这里尝试解释一些事情.让我们先澄清一些事情:

I can't give you a definite answer, but I'll try to explain a few things here. Let's start with clarifying something:

编译器知道 drop() 丢弃 x

这不是真的.虽然编译器知道标准库中有一些神奇"的东西,但 drop() 不是这样的 lang item.事实上,你可以自己实现 drop() ,这实际上是最简单的事情:

This is not true. While there are a few "magic" things in the standard library that the compiler knows about, drop() is not such a lang item. In fact, you could implement drop() yourself and it's actually the easiest thing to do:

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

该函数只是按值获取一些东西(因此,它被移到了 drop() 中),并且由于 drop() 内部没有发生任何事情,因此该值被丢弃在作用域的结尾,就像在任何其他函数中一样.所以:编译器不知道 x 被删除了,它只知道 x 被移动了.

The function just takes something by value (thus, it's moved into drop()) and since nothing happens inside of drop(), this value is dropped at the end of the scope, like in any other function. So: the compiler doesn't know x is dropped, it just knows x is moved.

您可能已经注意到,无论我们是否添加 drop() 调用,编译器错误都保持不变.现在,当涉及到引用时,编译器只会查看变量的范围.摘自 Niko Matsakis 对 NLL 的介绍:

As you might have noticed, the compiler error stays the same regardless of whether or not we add the drop() call. Right now, the compiler will only look at the scope of a variable when it comes to references. From Niko Matsakis' intro to NLL:

编译器当前的工作方式是,将引用分配给变量意味着其生命周期必须与该变量的整个范围一样大.

The way that the compiler currently works, assigning a reference into a variable means that its lifetime must be as large as the entire scope of that variable.

之后的博客中他的帖子:

特别是,今天,一旦生命周期必须超出单个语句的边界 [...],它必须一直延伸到封闭块的末尾.

In particular, today, once a lifetime must extend beyond the boundaries of a single statement [...], it must extend all the way till the end of the enclosing block.

这正是这里发生的事情,所以是的,您的问题与所有这些词汇借用"有关.从当前编译器的角度来看,表达式 &a 的生命周期需要至少与 x 的范围一样大.但这不起作用,因为引用将比 a 更有效,因为 x 的范围大于 a 的范围,正如指出的那样由编译器:

This is exactly what happens here, so yes, your problem has to do with all this "lexical borrowing" stuff. From the current compilers perspective, the lifetime of the expression &a needs to be at least as large as the scope of x. But this doesn't work, since the reference would outlive a, since the scope of x is larger than the scope of a as pointed out by the compiler:

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

而且我想你已经知道了所有这些,但是你可以通过交换行来修复你的例子 let mut x ...;let a ...;.

And I guess you already know all that, but you can fix your example by swapping the lines let mut x ...; and let a ...;.

我不确定当前提出的任何解决方案是否可以解决这个确切的问题.但我希望我们能尽快看到,因为所有这些都将作为 Rust 2017 路线图的一部分得到解决.阅读更新的好地方是这里(其中还包含链接到 Niko 的五篇相关博客文章).

I'm not sure whether or not this exact problem would be solved by any of the currently proposed solutions. But I hope that we will see soon enough, as all of this is being addressed as part of the Rust 2017 roadmap. A good place to read up on the updates is here (which also contains links to the five relevant blog posts of Niko).

这篇关于调用`drop`后移动的变量仍然借用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆