'Why doesn't rustc infer the type based on std trait implementations?

Consider the following code:

use std::net::IpAddr;

pub struct Server {
    host: IpAddr
}

impl Server {
    fn new(host: IpAddr) -> Self {
        Self {host}
    }
}

fn main() {
    let host = "192.168.0.1".parse().unwrap();
    let server = Server::new(host.clone());
}

rustc complains that it cannot infer the type of host, and that type annotations are needed in its definition.

Due to the method signature of Server::new(), (fn new(host: IpAddr) -> Self), Rust can conclude that the type of the expression host.clone() must be IpAddr. I can understand that rustc can't be certain of the type of host based on this alone because any type can implement a method named clone() returning an IpAddr, but given that rustc can't find any other types that implement a clone() method which returns IpAddr, is it a bridge too far for rustc to assume that that host is a type that implements std::clone::Clone, and returns an IpAddr and therefore must be an IpAddr itself? What is the danger of such assumption that motivated the design of rustc to fail to compile this?



Solution 1:[1]

host.clone() is opaque to the type inference algorithm until it knows what host is, because what host.clone() means depends on it.

This could only work if it was entirely unambiguous, and adding a new type with a clone() method would be sufficient to make it ambiguous:

struct Foo;

impl Foo {
    pub fn clone(&self) -> IpAddr { unimplemented!(); }
}

impl FromStr for Foo {
    type Err = ();
    fn from_str(_s: &str) -> Result<Foo, ()> { unimplemented!(); }
}

And this is even before we add in things like auto-deref, which means host could theoretically be some type implementing Deref<Target=IpAddr> as well.

Adding a new type to your program should never break type inference, but if the compiler looked around to see what host.clone() could be before it knows what host is, that's exactly what could happen.

If rustc did this, it would be useful in very few cases, and in those it would be very fragile.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1