How does iter() differ to a plain iteration over a HashMap? [duplicate] - for-loop

I am doing the Rust by Example tutorial which has this code snippet:
// Vec example
let vec1 = vec![1, 2, 3];
let vec2 = vec![4, 5, 6];
// `iter()` for vecs yields `&i32`. Destructure to `i32`.
println!("2 in vec1: {}", vec1.iter() .any(|&x| x == 2));
// `into_iter()` for vecs yields `i32`. No destructuring required.
println!("2 in vec2: {}", vec2.into_iter().any(| x| x == 2));
// Array example
let array1 = [1, 2, 3];
let array2 = [4, 5, 6];
// `iter()` for arrays yields `&i32`.
println!("2 in array1: {}", array1.iter() .any(|&x| x == 2));
// `into_iter()` for arrays unusually yields `&i32`.
println!("2 in array2: {}", array2.into_iter().any(|&x| x == 2));
I am thoroughly confused — for a Vec the iterator returned from iter yields references and the iterator returned from into_iter yields values, but for an array these iterators are identical?
What is the use case/API for these two methods?

TL;DR:
The iterator returned by into_iter may yield any of T, &T or &mut T, depending on the context.
The iterator returned by iter will yield &T, by convention.
The iterator returned by iter_mut will yield &mut T, by convention.
The first question is: "What is into_iter?"
into_iter comes from the IntoIterator trait:
pub trait IntoIterator
where
<Self::IntoIter as Iterator>::Item == Self::Item,
{
type Item;
type IntoIter: Iterator;
fn into_iter(self) -> Self::IntoIter;
}
You implement this trait when you want to specify how a particular type is to be converted into an iterator. Most notably, if a type implements IntoIterator it can be used in a for loop.
For example, Vec implements IntoIterator... thrice!
impl<T> IntoIterator for Vec<T>
impl<'a, T> IntoIterator for &'a Vec<T>
impl<'a, T> IntoIterator for &'a mut Vec<T>
Each variant is slightly different.
This one consumes the Vec and its iterator yields values (T directly):
impl<T> IntoIterator for Vec<T> {
type Item = T;
type IntoIter = IntoIter<T>;
fn into_iter(mut self) -> IntoIter<T> { /* ... */ }
}
The other two take the vector by reference (don't be fooled by the signature of into_iter(self) because self is a reference in both cases) and their iterators will produce references to the elements inside Vec.
This one yields immutable references:
impl<'a, T> IntoIterator for &'a Vec<T> {
type Item = &'a T;
type IntoIter = slice::Iter<'a, T>;
fn into_iter(self) -> slice::Iter<'a, T> { /* ... */ }
}
While this one yields mutable references:
impl<'a, T> IntoIterator for &'a mut Vec<T> {
type Item = &'a mut T;
type IntoIter = slice::IterMut<'a, T>;
fn into_iter(self) -> slice::IterMut<'a, T> { /* ... */ }
}
So:
What is the difference between iter and into_iter?
into_iter is a generic method to obtain an iterator, whether this iterator yields values, immutable references or mutable references is context dependent and can sometimes be surprising.
iter and iter_mut are ad-hoc methods. Their return type is therefore independent of the context, and will conventionally be iterators yielding immutable references and mutable references, respectively.
The author of the Rust by Example post illustrates the surprise coming from the dependence on the context (i.e., the type) on which into_iter is called, and is also compounding the problem by using the fact that:
IntoIterator is not implemented for [T; N], only for &[T; N] and &mut [T; N] -- it will be for Rust 2021.
When a method is not implemented for a value, it is automatically searched for references to that value instead
which is very surprising for into_iter since all types (except [T; N]) implement it for all 3 variations (value and references).
Arrays implement IntoIterator (in such a surprising fashion) to make it possible to iterate over references to them in for loops.
As of Rust 1.51, it's possible for the array to implement an iterator that yields values (via array::IntoIter), but the existing implementation of IntoIterator that automatically references makes it hard to implement by-value iteration via IntoIterator.

I came here from Google seeking a simple answer which wasn't provided by the other answers. Here's that simple answer:
iter() iterates over the items by reference
iter_mut() iterates over the items, giving a mutable reference to each item
into_iter() iterates over the items, moving them into the new scope
So for x in my_vec { ... } is essentially equivalent to my_vec.into_iter().for_each(|x| ... ) - both move the elements of my_vec into the ... scope.
If you just need to look at the data, use iter, if you need to edit/mutate it, use iter_mut, and if you need to give it a new owner, use into_iter.
This was helpful: http://hermanradtke.com/2015/06/22/effectively-using-iterators-in-rust.html

I think there's something to clarify a bit more. Collection types, such as Vec<T> and VecDeque<T>, have into_iter method that yields T because they implement IntoIterator<Item=T>. There's nothing to stop us to create a type Foo<T> if which is iterated over, it will yield not T but another type U. That is, Foo<T> implements IntoIterator<Item=U>.
In fact, there are some examples in std: &Path implements IntoIterator<Item=&OsStr> and &UnixListener implements IntoIterator<Item=Result<UnixStream>>.
The difference between into_iter and iter
Back to the original question on the difference between into_iter and iter. Similar to what others have pointed out, the difference is that into_iter is a required method of IntoIterator which can yield any type specified in IntoIterator::Item. Typically, if a type implements IntoIterator<Item=I>, by convention it has also two ad-hoc methods: iter and iter_mut which yield &I and &mut I, respectively.
What it implies is that we can create a function that receives a type that has into_iter method (i.e. it is an iterable) by using a trait bound:
fn process_iterable<I: IntoIterator>(iterable: I) {
for item in iterable {
// ...
}
}
However, we can't* use a trait bound to require a type to have iter method or iter_mut method, because they're just conventions. We can say that into_iter is more widely useable than iter or iter_mut.
Alternatives to iter and iter_mut
Another interesting thing to observe is that iter is not the only way to get an iterator that yields &T. By convention (again), collection types SomeCollection<T> in std which have iter method also have their immutable reference types &SomeCollection<T> implement IntoIterator<Item=&T>. For example, &Vec<T> implements IntoIterator<Item=&T>, so it enables us to iterate over &Vec<T>:
let v = vec![1, 2];
// Below is equivalent to: `for item in v.iter() {`
for item in &v {
println!("{}", item);
}
If v.iter() is equivalent to &v in that both implement IntoIterator<Item=&T>, why then does Rust provide both? It's for ergonomics. In for loops, it's a bit more concise to use &v than v.iter(); but in other cases, v.iter() is a lot clearer than (&v).into_iter():
let v = vec![1, 2];
let a: Vec<i32> = v.iter().map(|x| x * x).collect();
// Although above and below are equivalent, above is a lot clearer than below.
let b: Vec<i32> = (&v).into_iter().map(|x| x * x).collect();
Similarly, in for loops, v.iter_mut() can be replaced with &mut v:
let mut v = vec![1, 2];
// Below is equivalent to: `for item in v.iter_mut() {`
for item in &mut v {
*item *= 2;
}
When to provide (implement) into_iter and iter methods for a type
If the type has only one “way” to be iterated over, we should implement both. However, if there are two ways or more it can be iterated over, we should instead provide an ad-hoc method for each way.
For example, String provides neither into_iter nor iter because there are two ways to iterate it: to iterate its representation in bytes or to iterate its representation in characters. Instead, it provides two methods: bytes for iterating the bytes and chars for iterating the characters, as alternatives to iter method.
* Well, technically we can do it by creating a trait. But then we need to impl that trait for each type we want to use. Meanwhile, many types in std already implement IntoIterator.

.into_iter() is not implemented for a array itself, but only &[]. Compare:
impl<'a, T> IntoIterator for &'a [T]
type Item = &'a T
with
impl<T> IntoIterator for Vec<T>
type Item = T
Since IntoIterator is defined only on &[T], the slice itself cannot be dropped the same way as Vec when you use the values. (values cannot be moved out)
Now, why that's the case is a different issues, and I'd like to learn myself. Speculating: array is the data itself, slice is only a view into it. In practice you cannot move the array as a value into another function, just pass a view of it, so you cannot consume it there either.

IntoIterator and Iterator are usually used like this.
We implement IntoIterator for structures that has an inner/nested value (or is behind a reference) that either implements Iterator or has an intermediate "Iter" structure.
For example, lets create a "new" data structure:
struct List<T>;
// Looks something like this:
// - List<T>(Option<Box<ListCell<T>>>)
// - ListCell<T> { value: T, next: List<T> }
We want this List<T> to be iterable, so this should be a good place to implement Iterator right? Yes, we could do that, but that would limit us in certain ways.
Instead we create an intermediate "iterable" structure and implement the Iterator trait:
// NOTE: I have removed all lifetimes to make it less messy.
struct ListIter<T> { cursor: &List<T> };
impl<T> Iterator for ListIter<T> {
type Item = &T;
fn next(&mut self) -> Option<Self::Item> {...}
}
So now we need to somehow connect List<T> and ListIter<T>. This can be done by implementing IntoIterator for List.
impl<T> IntoIterator for List<T> {
type Item = T;
type Iter = ListIter<Self::Item>;
fn into_iter(self) -> Self::Iter { ListIter { cursor: &self } }
}
IntoIterator can also be implemented multiple times for container struct if for example it contains different nested iterable fields or we have some higher kinded type situation.
Lets say we have a Collection<T>: IntoIterator trait that will be implemented by multiple data structures, e.g. List<T>, Vector<T> and Tree<T> that also have their respective Iter; ListIter<T>, VectorIter<T> and TreeIter<T>. But what does this actually mean when we go from generic to specific code?
fn wrapper<C>(value: C) where C: Collection<i32> {
let iter = value.into_iter() // But what iterator are we?
...
}
This code is not 100% correct, lifetimes and mutability support are omitted.

Related

What's the fastest sound way to take ownership of elements of a Vec

Suppose I have the following:
fn into_three_tuple(mut v: Vec<String>) -> (String, String, String) {
if v.len() == 3 {
// ???
} else {
panic!()
}
}
What's should I replace ??? with to achieve the best performance?
Possible solutions
Sure, I could do
...
if v.len() == 3 {
let mut iter = v.into_iter();
(v.next().unwrap(), v.next().unwrap(), v.next().unwrap())
} else {
...
or similarly
if v.len() == 3 {
let mut iter = v.into_iter();
let e2 = v.pop.unwrap();
let e1 = v.pop.unwrap();
let e0 = v.pop.unwrap();
(e0, e1, e2)
} else {
...
Problems with those solutions
Both of these implementations use unwrap, which, if I understand correctly, performs a runtime check. But since we have the v.len() == 3 condition, we know the vector is guaranteed to have 3 elements, so the the runtime check is unnecessary.
Also, the into_iter solution may introduce the additional overhead of creating the iterator, and the pop solution may introduce the additional overhead of decreasing the v's internal len field, which seems silly since v will be dropped immediately after extracting the elements (so we don't care whether its len field is accurate).
Question
Is there some (possibly unsafe) way that's more efficient (e.g., some way to directly take ownership of elements at arbitrary indices)?
Or perhaps the compiler is already smart enough to skip these extraneous operations?
Or do I just have to live with suboptimal performance?
Note
In case you're wondering why I'm obsessing over such a tiny micro-optimization, I'm writing a fairly speed-critical application, and this function will be called a significant amount of times.
There is an operation provided in the standard library to extract a fixed number of items from a vector: converting it to an array.
use std::convert::TryInto; // needed only if not using 2021 edition / Rust 1.55 or earlier
pub fn into_three_tuple(v: Vec<String>) -> (String, String, String) {
let three_array: [String; 3] = v.try_into().unwrap();
let [a, b, c] = three_array;
(a, b, c)
}
I'm not really familiar with reading x86 assembly, but this does compile down to simpler code with fewer branches. I would generally expect that this is in most cases the fastest way to unpack a three-element vector; if it is reliably slower, then that would be a performance bug in the standard library which should be reported and fixed.
You should also consider using an array [String; 3] instead of a tuple in the rest of your program. The type is shorter to write, and they allow you to use array and slice operations to act on all three strings. Additionally, tuples do not have a guaranteed memory layout, and arrays do (even though practically they are likely to be identical in this case).
Changing the return type to be an array makes the function trivial — possibly useful for the type declaration, but not containing any interesting code:
pub fn into_three_array(v: Vec<String>) -> [String; 3] {
v.try_into().unwrap()
}
Disclaimer: As mentioned in the comments, you should benchmark to check that any of this actually makes a difference in your program. The fact that you're using many 3-element vectors (which are heap-allocated and therefore comparatively inefficient) shows that you may be over-optimizing, or optimizing at the wrong place. Having said that...
the into_iter solution may introduce the additional overhead of creating the iterator
Note that the "iterator" is a tiny on-stack value entirely transparent to the compiler, which can proceed to inline/eliminate it entirely.
Or perhaps the compiler is already smart enough to skip these extraneous operations?
In many cases, a check for v.len() == <concrete number> is indeed sufficient for the compiler to omit bounds checking because it has proof of the vector size. However, that doesn't appear to work with the approaches you've tried. After modifying the code to std::process::exit() if v.len() != 3 so the only panic is from the runtime checks, the runtime checks (as evidence by calls to panic) are still not removed either with the .pop() or with the into_iter() approach.
Is there some (possibly unsafe) way that's more efficient (e.g., some way to directly take ownership of elements at arbitrary indices)?
Yes. One approach is to use unreachable_unchecked() to avoid the panic where we can prove the calls to next() will succeed:
use std::hint::unreachable_unchecked;
pub fn into_three_tuple(v: Vec<String>) -> (String, String, String) {
if v.len() == 3 {
let mut v = v.into_iter();
unsafe {
let e0 = v.next().unwrap_or_else(|| unreachable_unchecked());
let e1 = v.next().unwrap_or_else(|| unreachable_unchecked());
let e2 = v.next().unwrap_or_else(|| unreachable_unchecked());
(e0, e1, e2)
}
} else {
panic!()
}
}
Modifying the code in the same way as the above shows no panic-related code.
Still, that relies on the compiler being smart enough. If you want to ensure the bound checks are not done, Rust unsafe allows you to do that as well. You can use as_ptr() to obtain a raw pointer to the elements stored in the vector, and read them from there directly. You need to call set_len() to prevent the vector from dropping the elements you've moved, but to still allow it to deallocate the storage.
pub fn into_three_tuple(mut v: Vec<String>) -> (String, String, String) {
if v.len() == 3 {
unsafe {
v.set_len(0);
let ptr = v.as_ptr();
let e0 = ptr.read();
let e1 = ptr.add(1).read();
let e2 = ptr.add(2).read();
(e0, e1, e2)
}
} else {
panic!("expected Vec of length 3")
}
}
The generated code again shows no bound check related panics, which is expected because there are no calls to functions that performs a checked access to data.

How to sort a Vector in descending order in Rust?

In Rust, the sorting methods of a Vec always arrange the elements from smallest to largest. What is a general-purpose way of sorting from largest to smallest instead?
If you have a vector of numbers, you can provide a key extraction function that "inverts" the number like this:
let mut numbers: Vec<u32> = vec![100_000, 3, 6, 2];
numbers.sort_by_key(|n| std::u32::MAX - n);
But that's not very clear, and it's not straightforward to extend that method to other types like strings.
There are at least three ways to do it.
Flipped comparison function
vec.sort_by(|a, b| b.cmp(a))
This switches around the order in which elements are compared, so that smaller elements appear larger to the sorting function and vice versa.
Wrapper with reverse Ord instance
use std::cmp::Reverse;
vec.sort_by_key(|w| Reverse(*w));
Reverse is a generic wrapper which has an Ord instance that is the opposite of the wrapped type's ordering.
If you try to return a Reverse containing a reference by removing the *, that results in a lifetime problem, same as when you return a reference directly inside sort_by_key (see also this question). Hence, this code snippet can only be used with vectors where the keys are Copy types.
Sorting then reversing
vec.sort();
vec.reverse();
It initially sorts in the wrong order and then reverses all elements.
Performance
I benchmarked the three methods with criterion for a length 100_000 Vec<u64>. The timing results are listed in the order above. The left and right values show the lower and upper bounds of the confidence interval respectively, and the middle value is criterion's best estimate.
Performance is comparable, although the flipped comparison function seems to be a tiny bit slower:
Sorting/sort_1 time: [6.2189 ms 6.2539 ms 6.2936 ms]
Sorting/sort_2 time: [6.1828 ms 6.1848 ms 6.1870 ms]
Sorting/sort_3 time: [6.2090 ms 6.2112 ms 6.2138 ms]
To reproduce, save the following files as benches/sort.rs and Cargo.toml, then run cargo bench. There is an additional benchmark in there which checks that the cost of cloning the vector is irrelevant compared to the sorting, it only takes a few microseconds.
fn generate_shuffled_data() -> Vec<u64> {
use rand::Rng;
let mut rng = rand::thread_rng();
(0..100000).map(|_| rng.gen::<u64>()).collect()
}
pub fn no_sort<T: Ord>(vec: Vec<T>) -> Vec<T> {
vec
}
pub fn sort_1<T: Ord>(mut vec: Vec<T>) -> Vec<T> {
vec.sort_by(|a, b| b.cmp(a));
vec
}
pub fn sort_2<T: Ord + Copy>(mut vec: Vec<T>) -> Vec<T> {
vec.sort_by_key(|&w| std::cmp::Reverse(w));
vec
}
pub fn sort_3<T: Ord>(mut vec: Vec<T>) -> Vec<T> {
vec.sort();
vec.reverse();
vec
}
use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn comparison_benchmark(c: &mut Criterion) {
let mut group = c.benchmark_group("Sorting");
let data = generate_shuffled_data();
group.bench_function("no_sort", |b| {
b.iter(|| black_box(no_sort(data.clone())))
});
group.bench_function("sort_1", |b| {
b.iter(|| black_box(sort_1(data.clone())))
});
group.bench_function("sort_2", |b| {
b.iter(|| black_box(sort_2(data.clone())))
});
group.bench_function("sort_3", |b| {
b.iter(|| black_box(sort_3(data.clone())))
});
group.finish()
}
criterion_group!(benches, comparison_benchmark);
criterion_main!(benches);
[package]
name = "sorting_bench"
version = "0.1.0"
authors = ["nnnmmm"]
edition = "2018"
[[bench]]
name = "sort"
harness = false
[dev-dependencies]
criterion = "0.3"
rand = "0.7.3"

Unable to collect a filtered a Vec into itself [duplicate]

This question already has answers here:
is it possible to filter on a vector in-place?
(4 answers)
Closed 3 years ago.
I've started working through the Project Euler problems in Rust and came across #3 where the easiest quick-approach would be to implement a Sieve of Eratosthenes.
In doing so, my algorithm creates an iterator to then filter non-primes out of and assign it back to the original vector, but I'm receiving an error that Vec<u32> can't be built from Iterator<Item=&u32>.
Code:
fn eratosthenes_sieve(limit: u32) -> Vec<u32> {
let mut primes: Vec<u32> = Vec::new();
let mut range: Vec<u32> = (2..=limit).collect();
let mut length = range.len();
loop {
let p = range[0];
primes.push(p);
range = range.iter().filter(|&n| *n % p != 0).collect();
if length == range.len() {
break;
}
length = range.len();
}
primes
}
Error:
error[E0277]: a collection of type `std::vec::Vec<u32>` cannot be built from an iterator over elements of type `&u32`
--> src\main.rs:42:55
|
42 | range = range.iter().filter(|&n| *n % p != 0).collect();
| ^^^^^^^ a collection of type `std::vec::Vec<u32>` cannot be built from `std::iter::Iterator<Item=&u32>`
|
= help: the trait `std::iter::FromIterator<&u32>` is not implemented for `std::vec::Vec<u32>`
Why is the closure wrapping the values in extra borrows?
Explanation
According to the error message, the expression range.iter().filter(|&n| *n % p != 0) is an iterator over items of type &u32: a reference to an u32. You expected an iterator over u32 by value. So let's walk backwards:
The filter(...) part of the iterator chain has actually nothing to do with your problem. When we take a look at Iterator::filter, we see that it returns Filter<Self, P>. This type implements Iterator:
impl<I: Iterator, P> Iterator for Filter<I, P>
where
P: FnMut(&I::Item) -> bool,
{
type Item = I::Item;
// ...
}
The important part here is that type Item = I::Item, meaning that the item type of I (the original iterator) is passed through exactly. No reference is added.
This leaves .iter(): that's the cause of the problem. Vec::iter returns slice::Iter<T> which implements Iterator:
impl<'a, T> Iterator for Iter<'a, T> {
type Item = &'a T;
// ...
}
And here we see that the item type is a reference to T (the element type of the vector).
Solutions
In general cases, you could call .cloned() on any iterator that iterates over references to get a new iterator that iterates over the items by value (by cloning each item). For types that implement Copy you can (and should) use .copied(). E.g. range.iter().filter(|&n| *n % p != 0).copied().collect().
However, in this case there is a better solution: since you don't need the vector afterwards anymore, you can just call into_iter() instead of iter() in order to directly get an iterator over u32 by value. This consumes the vector, making it inaccessible afterwards. But, as said, that's not a problem here.
range = range.into_iter().filter(|&n| n % p != 0).collect();
Also note that I removed the * in *n, as the dereference is not necessary anymore.
Other hints
Always reallocating a new vector is not very fast. The Sieve of Eratosthenes is classically implemented in a different way: instead of storing the numbers, one only stores Booleans to denote for each number if it's prime or not. The numbers are never stored explicitly, but implicitly by using the indices of the vector/array.
And to make it really fast, one should not use a Vec<bool> but instead a dedicated bitvec. Vec<bool> stores one byte per bool, although only one bit would be necessary. The de-facto crate that offers such a bit vector is bit-vec, which conveniently also shows an example implementation of Sieve of Eratosthenes in its documentation.

Why is a trait bound present in the where clause but not in the function signature?

I'm reading HashMap's get function, but I can't find the type parameter K in the source code.
Why does the K trait bound exist in the where clause, but not in the function signature?
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Hash + Eq
{
self.search(k).map(|bucket| bucket.into_refs().1)
}
K is a type parameter of HashMap<K, V, S> and it's introduced at the beginning of the applicable impl block:
impl<K, V, S> HashMap<K, V, S>
where K: Eq + Hash,
S: BuildHasher
It is applicable for the whole block, including get, which adds an additional constraint, K: Borrow<Q>.
This way of specifying the type of get's k might be a bit awkward, but it enables us to e.g. do the following:
let mut map: HashMap<String, usize> = HashMap::new();
map.insert("herp".to_string(), 1);
map.insert("derp".to_string(), 2);
assert_eq!(map.get("herp"), Some(&1)); // we can search by &'static str (not only by a String)
I think the search method in get method body use K: Borrow<Q> trait bounds so the get method needs the same trait bounds.
And about using &str or &String for key values in get method parameters,
It's enough to use only &Q type

Creating a Vector of Vectors in Rust

This code won't compile:
fn main() {
let m1 = vec![1, 2, 3];
let m2 = vec![&m1, &m1, &m1];
let m3 = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
for i in &m2 {
for j in i {
println!("{}", j);
}
}
for i in &m3 {
for j in i {
println!("{}", j);
}
}
}
error[E0277]: the trait bound `&&std::vec::Vec<{integer}>: std::iter::Iterator` is not satisfied
--> src/main.rs:8:18
|
8 | for j in i {
| ^ `&&std::vec::Vec<{integer}>` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `&&std::vec::Vec<{integer}>`
= note: required by `std::iter::IntoIterator::into_iter`
How is m2 different than m3 such that m3 causes no issues, but m2 prevents compilation?
Is there an easier way to create a vector of vector of... to any desired depth? The way I have it working (m3) seems so clunky.
How is m2 different than m3 ...
Check the types step by step. m1 is of type Vec<isize> (it could be any other integer type as well, but I assume it's isize for now). Why? Because the elements in the vec![] macro are of type isize. Now you are creating m2:
let m2 = vec![&m1, &m1, &m1];
What is the type of the elements in this macro? Well we already said m1 has the type Vec<isize>, so &m1 has the type &Vec<isize>. So the resulting type of m2 is Vec<&Vec<isize>> (a vector full of references to other vectors).
However, m3 is of type Vec<Vec<isize>>, since the elements in the (outer) vec![] macro are of type Vec<isize> (no reference!).
Hint: to easily check the type of any variable (such as foo), type:
let _: () = foo;
This will result in a compiler error that tells you the type of foo.
... such that m3 causes no issues, but m2 prevents compilation?
Now that we know the types of m2 and m3, lets look at the loops. for loops work by accepting something that implements IntoIterator. You are passing &m2, which is of type &Vec<&Vec<isize>> (note the two references). We can see, that IntoIterator is indeed implemented for a reference to a vector:
impl<T> IntoIterator for &Vec<T> {
type Item = &T
// ...
}
This means that you get an iterator that spits out references to the inner type T (type Item = &T). Our inner type of m2 is &Vec<isize>, so we will get items of type &&Vec<isize> (two references!). Your variable i has this exact type.
Then you want to iterate again with this inner loop:
for j in i { ... }
But i has this double-reference type and there isn't an implementation of IntoIterator for that type. To iterate it, you have to either dereference it like:
for j in *i { ... }
Or even better: make i be of the type &Vec<isize> (one reference!) by stripping it away with pattern matching in the outer loop:
for &i in &m2 { ... }
Your m3 loop does the same, but since m3 is of another type (with one reference less), it works (I hope you can see why).
Is there an easier way to create a vector of vector of... to any desired depth
Even if m2 worked, it wouldn't hold the same values as m3. To make m2 of the type Vec<Vec<isize>> (like m3), you should clone m1 instead of taking a reference to it.
let m2 = vec![m1.clone(), m1.clone(), m1.clone()];
We can do even better by using the vec![_; _] form of the macro:
let m2 = vec![m1; 3]; // three times the value of `m1`
As a last note, you should consider not using nested Vecs. The nesting creates overhead because the values are spread over the whole memory instead of being in one place.

Resources