[Resolved] Why cloning Option<&IpAddr> doesn't work in this code?

I am writing a function to do DNS resolution on a hostname, but I don’t quite understand what is happening.

The function I wrote is below:

fn resolve_host(host: &str) -> Option<IpAddr> {
    let either_addresses: io::Result<Vec<IpAddr>> =
        (host, 0).to_socket_addrs()
                 .map(|iter| iter.map(|socket_address| socket_address.ip()).collect());

    if let Ok(addresses) = either_addresses {
         addresses.first().clone()  // this line here is the issue
    } else {
        None
    }
}

But if I do this, I get a compiler error:

   |
45 | fn resolve_host(host: &str) -> Option<IpAddr> {
   |                                -------------- expected `std::option::Option<std::net::IpAddr>` because of return type
...
51 |         addresses.first().clone()
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::net::IpAddr`, found reference
   |
   = note: expected type `std::option::Option<std::net::IpAddr>`
              found type `std::option::Option<&std::net::IpAddr>`

I don’t get why this happens. I wrote a small program to try to replicate it, but I get different results. The one below compiles just fine.

fn main() {
    let addr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
    let some_addr: Option<&IpAddr> = Some(addr);

    println!("{:?}", some_addr.clone());
}

What is it that is incorrect in my resolve_host function?

I worked around it by replacing the problematic line with Some(addresses.first().unwrap().clone()),
but this is quite ugly :frowning_face:

Citation needed.

In any case, .clone() gives you something of the same type. It clones Option<&T> to another Option<&T>. What you need is .cloned() which gives Option<T> instead. (This method is an inherent method of Option, while .clone() is available for all clone-able types. Iterators also have a .cloned() adapter, which clones every item.)

Oh, that makes sense. I didn’t notice that about clone(). Thanks @birkenfeld!

Just noticed I mistyped the second example when I wrote it here. Missed the & in = Some(&addr).
But it makes sense why it worked. println! was able to handle the Option<&IpAddr>.