for循环如何实现into_iter



跟进这个被标记为重复的问题

for循环如何实现into_iter的概念一直困扰着我,这个答案给我带来了更多的问题,比如re-borrow,在我们的官方文件中除了一个地方没有提到。

根据我对这个评论的理解,当vec是一个可变引用时,for i in vec.into_iter()实际上是for i in (&mut *vec).into_iter()

for i in vec呢,是不是真的是i in vec.into_iter()?是否有任何地方有更多关于如何实现循环的细节,以及如何触发再借款以及它是如何工作的?

参考代码:
fn question1_1(vec: &mut [i32]) {
for &mut item in vec.into_iter() {
println!("{}", item);
}
for &mut item in vec { // --- `vec` moved due to this implicit call to `.into_iter()`
println!("{}", item);
}
vec; // Error: move occurs because `vec` has type `&mut [i32]`, which does not implement the `Copy` trait
}
pub fn main() {
let mut s = vec![1, 2, 3];
question1_1(&mut s);

for循环被设计成(这可以通过检查HIR看到):

{
let _t = match IntoIterator::into_iter(iter) {
mut iter => loop {
match Iterator::next(&mut iter) {
None => break,
Some(i) => {
// Body
}
}
},
};
_t
}

具体来说,通过执行IntoIterator::into_iter(iterable)将可迭代对象转换为迭代器。每个trait,包括IntoIterator,都有一个隐藏的Self通用参数,所以这实际上是IntoIterator::<_>::into_iter(iterable)。从重新借用POV,这类似于:

fn foo<T>(v: T) {}
foo::<_>(iterable)

确切的细节在Do可变引用有移动语义?,但一般的想法是,它没有被记录下来。当前的工作是这样的,当编译器不能不加推断地确定某物是可变引用时,它不会被重新借用。因为_需要推理,所以不能被重新借用。

接收器的工作方式不同(总是被重新借用),因此iterable.into_iter()确实执行了重新借用。事实上,这种行为与autoref有关,而与reborrowing无关。参见Rust'确切的自动解引用规则是什么?

除了在操场上使用HIR来检查for循环在幕后是如何运行的,这里是关于for循环如何去糖的官方文档。

从文档给出的示例中,values (vec类型)被传递给IntoIterator::into_iter()IntoIterator::into_iter(values),这与作为方法调用values.into_iter()不同。

let values = vec![1, 2, 3, 4, 5];
for x in values {
println!("{}", x);
}

De-sugared进

let values = vec![1, 2, 3, 4, 5];
{
let result = match IntoIterator::into_iter(values) {
mut iter => loop {
let next;
match iter.next() {
Some(val) => next = val,
None => break,
};
let x = next;
let () = { println!("{}", x); };
},
};
result
}

最新更新