'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 |