I have a function that returns some object. The caller of this function should not care about the actual type but the traits the type implements:
trait CanWalk {
fn walk(&self) {}
}
trait CanFly {
fn fly(&self) {}
}
struct Woodpecker {}
impl CanWalk for Woodpecker {}
impl CanFly for Woodpecker {}
fn make_woodpecker() -> CanWalk + CanFly {
Woodpecker {}
}
fn main() {}
The compiler complains:
error[E0225]: only auto traits can be used as additional traits in a trait object
--> src/main.rs:14:35
|
14 | fn make_woodpecker() -> CanWalk + CanFly {
| ^^^^^^ non-auto additional trait
Why is that? What could I do instead?
In my actual project, I have a few functions that do I/O on streams (or basically anything that supports Read + Write
). Therefore, the signature looks like this:
fn do_some_io<T: Read + Write>(io_thing: T)
Usually, that would be a native_tls::TlsStream
but I would also want to be able to pass a std::net::TcpStream
if the user says so (during runtime). Something along these lines:
fn connect_tcp(host: &str, ...) -> Result<Read + Write> {...}
fn connect_tls(host: &str, ...) -> Result<Read + Write> {...}
fn connect(insecure: bool, host: &str, ...) -> Result<Read + Write> {
if insecure {
connect_tcp(...)
} else {
connect_tls(...)
}
}
If trait objects with two bounds do not work (yet?), how could I implement this functionality in Rust?