Is it possible to use `Iterator::map` in a ToSocketAddrs impl? (associated types involving closures)

It seems like it ought to be possible to use Iterator::map (and other iterator combinators) to avoid a lot of extra typing when defining a ToSocketAddrs impl, something like this:

use std::io;
use std::iter;
use std::net::{IpAddr, SocketAddr, ToSocketAddrs};
use std::range::{Range, RangeIter};

pub struct PortRange {
    addr: IpAddr,
    range: Range<u16>,
}
impl PortRange {
    pub fn new(addr: IpAddr, range: Range<u16>) -> PortRange {
        PortRange { addr, range }
    }
}
impl ToSocketAddrs for PortRange {
    type Iter = iter::Map<RangeIter<u16>, _>; // <-- problem here
    fn to_socket_addrs(&self) -> io::Result<Self::Iter> {
        Ok(self
            .range
            .iter()
            .map(|port| SocketAddr::new(self.addr, port)))
    }
}

(Playground)

The problem is that the second type argument to iter::Map needs to be the type of the closure, or something close to it, and I haven't been able to find a way to name that type. If you compile the above as is you get

error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types

I tried changing the placeholder to FnMut(u16)->SocketAddr and impl FnMut(u16)->SocketAddr but those just gave me different errors.

You can do it on unstable with ITIAT (or just TAIT[1]), though I'd probably just use impl Iterator<Item = u16> for the entire associated type.

With stable I believe you need to use Box<dyn FnMut(u16) -> SocketAddr>, or fn(u16) -> SocketAddr if possible (you're capturing state so it is not possible), or go through the rigamarole of having your own Iterator type that manually does the mapping in the implementation instead of using a closure. (I.e. on stable AFAIK there is no way to name a specific closure.)


  1. type = impl Trait ↩︎