I tried to implement two permutation iterators, one which returns references to the input data in the permutations, the other clones the data. I tried to make this as generic as possible and to reuse the core iterator function next() in both cases (as the only difference would be putting a referenced vs. a cloned value into the next result vector). I never used PhantomData before, but the compiler strongly suggested to use it.
Now my question: is this the right way to do it? Is there a simpler way?
Instead of providing exactly “cloned” and “uncloned”, I'd make permute() take a user-supplied function which produces the item to be put in the Vec. Then there will be no special purpose trait (just FnMut(&T) -> U) and no PhantomData (because the function is an actual, not phantom, value). The function can then be Clone::clone or the identity function to produce your two desired results, or other things such as copying only one field from the input.
The general principle here is: if you have to pay the cost of allocating a data structure to return to your caller, let the caller control what goes in that data structure, so that they don't have to reallocate to convert it to what they actually need.
That would be the next level of generalisation, but while working toward what I have, I got in trouble supplying a general function Fn(&T) -> B to any B into the base struct Permutator. As that was my original idea working toward generalisation: do this, and then create three permute functions, one uncloned, one cloned, and one where the user provides a function that may map the value &T to the universe. But I did not get it working.
I also got rid of -> impl Iterator as returning nominal types is generally nicer for the caller (but does lock you in to some things by exposing more details).
The caller will have access to all the other traits the iterator implements (eg. with just impl Iterator, you'll lose access to ExactSizeIterator, DoubleEndedIterator, or even plain old Clone, Debug, etc.)