以下代码编译:
fn consume(_: Box<u64>) {}
let tuple = (Some(Box::new(1)), Some(Box::new(2)));
match tuple {
(Some(x), Some(y)) => {
consume(x);
consume(y);
}
_ => (),
}
以下代码编译:
fn consume(_: Box<u64>) {}
match [Some(Box::new(1)), Some(Box::new(2))] {
[Some(x), Some(y)] => {
consume(x);
consume(y);
}
_ => (),
}
但是此代码无法编译:
fn consume(_: Box<u64>) {}
let array = [Some(Box::new(1)), Some(Box::new(2))];
match array {
[Some(x), Some(y)] => {
consume(x);
consume(y);
}
_ => (),
}
编译器说:
error[E0382]: use of moved value: `(array[..] as std::prelude::v1::Some).0`
--> src/main.rs:5:24
|
5 | [Some(x), Some(y)] => {
| - ^ value used here after move
| |
| value moved here
|
= note: move occurs because the value has type `std::boxed::Box<u64>`, which does not implement the `Copy` trait
为什么要编译第一和第二个版本,而不是第三个版本?
答案 0 :(得分:3)
意外地,第三版没有编译。如here所述,匹配盒装值时会发生相同的问题。
从链接的答案中引用错误的解释:
我唯一的猜测是
Box
的所有权移到了第一个 参数,提取参数,然后编译器尝试移动它 再次进入下一个参数。
用“ array”替换“ Box
”,您将获得匹配数组时的解释。链接答案中提供的一种解决方案也适用于匹配数组-使用花括号将Box
/ array完全移动到match表达式中:
fn consume(_: Box<u64>) {}
let array = [Some(Box::new(1)), Some(Box::new(2))];
match {array} {
[Some(x), Some(y)] => {
consume(x);
consume(y);
}
_ => (),
}
答案 1 :(得分:3)
以下是代码的简化版本:
struct NonCopy;
fn main() {
// OK
let tuple = (Some(NonCopy), Some(NonCopy));
if let (Some(_x), Some(_y)) = tuple {}
// OK
if let [Some(_x), Some(_y)] = [Some(NonCopy), Some(NonCopy)] {}
// Fails
let array = [Some(NonCopy), Some(NonCopy)];
if let [Some(_x), Some(_y)] = array {}
}
此代码在non-lexical lifetimes are enabled时保持原样。
非词汇生存期还不稳定。
将数组的所有权明确转移到match
或if let
头表达式中:
let array = [Some(NonCopy), Some(NonCopy)];
if let [Some(_x), Some(_y)] = { array } {}
借阅检查器的当前实现是基于AST的,而将来的实现将是基于MIR的。在较高的层次上,您可以将其视为“处理我键入的代码”(AST)和“处理代码中的逻辑数据流”(MIR)。
某些“黑客”已添加到AST借阅检查器中,这就是为什么您可以成功使用数组文字而不是变量的原因。借助MIR借阅检查器,此类大型黑客将消失,借阅检查器也将变得更加精确,从而可以编译更多代码。