I realize the iterator needs to keep the Vec around so I can't just give it a Vec that will be out of scope after this function returns. I tried multiple things but ended up with a dirty hack:
What you’ve got isn’t terrible; the main issue you’re running into is that every codepath has to return the same concrete type. There are a few additional choices, but I’m not convinced any of them is better than what you already have:
Return Option<impl Iterator<...>>
Use dynamic dispatch, and return a Box<dyn Iterator<...>>
Make an enum that has variants for both std::iter::Empty and the iter::Map, and implement Iterator for it.
If it were me, I’d probably move the static inside the function body and call it a day.
&[] is an empty slice zero length array, so a reference to some 0 elements of data. That means it does not need a valid pointer and it can be created at any time with any lifetime.
&Vec::new() is a reference to an empty Vec. But that Vec needs to live somewhere. You could use a static empty Vec for it, but a slice is cleaner.