In the original solution, I used the Iterator::map method, which has the type of the closure as part of the Map<Self, F> return type (it's the F). In Rust, every single closure has its own unique type, which is what allows the compiler to optimize code using iterators down to the same assembly as the corresponding loop. However, the types of these closures do not have a name that is usable in the source code, and since it is part of the type of Map, this makes it impossible to specify the IntoIter associated type if you are using Map.
To get around this, I reimplemented the Map iterator from the standard library in the MyCustomIterator type, and hardcoded it to call as_str() instead of a user-provided closure. This allows me to give the IntoIter associated type a name. Note that the map used in my custom iterator is not the same as the one I used previously. In this case, it is Option::map.
The reason using Iterator::map is fine with the fn iter approach I initially suggested is that in the return type of functions, the impl Trait syntax allows me to say "this returns some type that implements Iterator" without saying which one, sidestepping the no-name issue of using closures.
This feature cannot be used in associated types, however.