Flat_map returning iterator of references

Hello, I am still quite new to Rust and I am trying to learn how to deal properly with references.

I am trying to use .flat_map() on a vector of length 3, that i create inside the function as follows

let points: Vec<(MyType, bool)> = 
    some_vec.flat_map(|[a,b,c]| 
        [
            (MyType{a.some_property()}, false),
            (MyType{b.some_property()}, true),
            (MyType{c.some_property()}, true),
        ].into_iter()
    )
    .collect();

But it seems that flat_map returns a reference to the tuples created, instead passing the ownership to the new function

value of type `Vec<(MyType, bool)>` cannot be built from `Iterator<Item=&(MyType, bool)>

If i then try to add a .map(|&t| t) before .collect() the compiler complains that

cannot return value referencing temporary value

returns a value referencing data owned by the current functionrustc(E0515)
printer.rs(226, 17): returns a value referencing data owned by the current function
printer.rs(226, 17): temporary value created here

I have tried searching on the various errors, but cant seem to find the right solution. So if anyone could point me in the right direction, I would greatly appriciate it!

You've stumbled on the issue of arrays not actually having a true consuming into_iter(). The […].into_iter() actually calls this impl – IntoIterator for &'a [T; N] – and thus is actually equivalent to iter().

There are several possible fixes:

  • if your type is Copy, add copied()[…].iter().copied().
  • you can use vec instead of array – vec![…].into_iter()
  • std::iter::onces .chain()ed together.
  • (on nightly) use std::array::IntoIterIntoIter::new([…])

This would actually work, but must be done inside the flat_map. (this is actually equivalent to .copied()).

2 Likes

Thank you for the fast response!

Ah, I didn't know that Rust had Arrays and not just Vecs - the vec![...] did the job me.

Yeah, Rust has both, but arrays are a little bit of second-class citizen (like this missing into_iter(), or missing some traits, etc.), so usually usage of Vec is recommended.

Keep in mind that vec implies an allocation, so you should be careful with "just use vec" for perf-sensitive code. (in your particular case, if it's perf-sensitive, I'd go with copied()/map(|&x|x)).

Anyway, const-generics are on their way and arrays becoming less second-class with every release :slight_smile:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.