Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is IntoIter not owning the values? [duplicate]

I want to iterate over the bytes of an integer:

use core::mem::size_of;

const SIZE: usize = size_of::<u64>();
    
fn main() {
    let x: u64 = 512;
    let mut buf: [u8; SIZE] = [0; SIZE];
    
    for (i, b) in x.to_be_bytes().into_iter().enumerate() {              
        buf[i] = b;
    }
}

The compiler tells me for the line buf[i] = b; that he expected `u8`, found `&u8` . But why?

When I take a look at the implementation of the IntoIterator trait for the owned array type [T; N] the into_iter() method returns a std::array::IntoIter<T, N> which implements the Iterator trait where type Item = T. Shouldn't T evaluate to u8 here?

Why is the iterator returning &u8 references instead of owned u8 bytes?

like image 444
David Avatar asked Sep 28 '21 09:09

David


Video Answer


1 Answers

The Rust documentation mentions this behavior for array:

Prior to Rust 1.53, arrays did not implement IntoIterator by value, so the method call array.into_iter() auto-referenced into a slice iterator. Right now, the old behavior is preserved in the 2015 and 2018 editions of Rust for compatibility, ignoring IntoIterator by value. In the future, the behavior on the 2015 and 2018 edition might be made consistent to the behavior of later editions.

  • Rust documentation, "Primitive Type array"

You will get references if you're using Rust 2018, but for the time being you can use IntoIterator::into_iter(array)

Dereferencing the b within the loop will hint at this:

  |
9 |     for (i, b) in x.to_be_bytes().into_iter().enumerate() {
  |                                   ^^^^^^^^^
  |
  = note: `#[warn(array_into_iter)]` on by default
  = warning: this changes meaning in Rust 2021
  = note: for more information, see issue #66145 <https://github.com/rust-lang/rust/issues/66145>

Here's an example:

use core::mem::size_of;

const SIZE: usize = size_of::<u64>();

fn main() {
    let x: u64 = 512;
    let mut buf: [u8; SIZE] = [0; SIZE];

    for (i, b) in IntoIterator::into_iter(x.to_be_bytes()).enumerate() {
        buf[i] = b;
    }
}
  • Playground

The Rust 2021 edition, with the new behavior, will likely land this October. See Rust Blog, "The Plan for the Rust 2021 Edition" for more information.

like image 58
Jason Avatar answered Oct 30 '22 23:10

Jason