title: How do I overcome match arms with incompatible types for structs implementing same trait?
body: <p>I am attempting to write the <code>cat</code> command to learn Rust, but I can't seem to convert command line arguments into reader structs.</p>
  
  <pre><code>use std::{env, io};
  use std::fs::File;
  
  fn main() {
      for arg in env::args().skip(1) {
          let reader = match arg.as_str() {
              "-" =&gt; io::stdin(),
              path =&gt; File::open(&amp;path).unwrap(),
          };
      }
  }
  </code></pre>
  
  <p>Error:</p>
  
  <pre class="lang-none prettyprint-override"><code>error[E0308]: match arms have incompatible types
   --&gt; src/main.rs:6:22
    |
  6 |         let reader = match arg.as_str() {
    |                      ^ expected struct `std::io::Stdin`, found struct `std::fs::File`
    |
    = note: expected type `std::io::Stdin`
    = note:    found type `std::fs::File`
  note: match arm with an incompatible type
   --&gt; src/main.rs:8:21
    |
  8 |             path =&gt; File::open(&amp;path).unwrap(),
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^
  </code></pre>
  
  <p>It doesn't seem like it's possible to polymorphically match trait implementers <a href="https://stackoverflow.com/questions/26126683/how-to-match-trait-implementors">(related)</a>. How can I use either a <code>File</code> or <code>Stdin</code> as a reader?</p>