2

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Jan
  • 293
  • 1
  • 11
  • I believe your question is answered by the answers of [Can I get a borrow of a multi-trait instance as function parameter without using a generic type?](https://stackoverflow.com/q/28897297/155423). If you disagree, please [edit] your question to explain the differences. Otherwise, we can mark this question as already answered. – Shepmaster Jun 21 '18 at 15:02
  • I wrote an answer but @Shepmaster pointed out that it only works on the MCVE and not for `connect`. I suspect the answer you want is something like `-> Result>` where `trait Stream` has `Read` and `Write` as supertraits. – trent Jun 21 '18 at 15:52
  • (And `Read` and `Write` are implemented for `Box`) – trent Jun 21 '18 at 15:52
  • I'd add in [What is the correct way to return an Iterator (or any other trait)?](https://stackoverflow.com/q/27535289/155423) as a duplicate to address the `Box` aspect (and maybe [Conditionally iterate over one of several possible iterators](https://stackoverflow.com/q/29760668/155423)). – Shepmaster Jun 21 '18 at 16:04

0 Answers0