I didn't realize that calling into_iter
on Box<[T]>
would return an iterator over references before edition 2024 until I read Edition Guide. This makes me curious about how calling into_iter
on Box<[T; N]>
does now (in edition 2024), given that Box<[T; N]>
does not yet implement IntoIterator
.
According to the The Dot Operator section of The Rustonomicon, it should first dereference to &[T; N]
, then unsize to &[T]
, suggesting that it should behave like calling into_iter
on Box<[T]>
used to — returning an iterator over references. However, this compiles:
struct Foo;
fn take(val: Foo) {}
fn main() {
let array: Box<[Foo; 1]> = Box::new([Foo]);
for foo in array.into_iter() {
take(foo);
}
}
Is it because the mysterious DerefMove
is doing something?
(About the DerefMove
, I know it does not exist. Some people think there should be a DerefMove
trait to cancel the uniqueness of Box
, so I use this term here just to describe this dereference behavior of Box
)
Is it because the mysterious
DerefMove
is doing something?
There is no DerefMove
. Box
is a lang_item which means the compiler can understand that a Box
can be moved-from, unlike other pointers.
The items you quote are about slices, but Box<[T; N]>
is a boxed array not a slice. So it can deref to the array, which then invokes
impl<T, const N: usize> IntoIterator for [T; N]
which was added in edition 2021 in Rust 1.53
demo on godbolt, note how the code compiles in Edition 2021, but not in Edition 2018
And if you remove the -O
and look at the assembly you can see that it references array::iter_inner
, whereas boxed slices go through vec::into_iter::IntoIter
, which you can also see if you replace the boxed array Box<[Foo; 1]>
by a boxed slice Box<[Foo]>
.