Polymorphism with mixed ownership (match of File vs stdout)


#1

I’d love to make this code work:

    let arg = "-";
    match arg {
        "-" => std::io::stdout() // as &std::io::Write,
        path => File::create(&path).unwrap() // as &std::io::Write,
    }
    .write_all("blah".as_bytes()).unwrap();

Both arms of the match implement std::io::Write, but they’re different types with different ownership, so I’m struggling to unify them to get a neat polymorphic .write_all() call. (I know I could duplicate the .write_all() call, but then it wouldn’t be neat any more :slight_smile: )


#2

You can’t borrow them, since they are owned by their match arms, but you can box them: https://is.gd/PRz7Zo You can also avoid some indirection by putting them in an enum and implement Write for it. I think it has only two required methods.


#3

You need to declare the storage beforehand if you want to borrow them:

use std::fs::File;
use std::io;

fn main() {
    let arg = "-";
    let mut file;
    let mut stdout;
    let output: &mut std::io::Write = match arg {
        "-" => {
            stdout = io::stdout();
            &mut stdout
        }
        path => {
            file = File::create(&path).unwrap();
            &mut file
        },
    };
    output.write_all("blah".as_bytes()).unwrap();
}

#4

Got it. Thank you.