Hi, the below works as expected, that is, I can pass as an arg to that fn any csv reader, be it created from file, stdin etc. fn bar<R: std::io::Read>(rdr:&mut csv::Reader<R>) {}//works
Box::new(rdr)
| -------- ^^^ expected Reader<R>, found Reader<Stdin>
| |
| arguments to this function are incorrect
|
= note: expected struct csv::Reader<R>
found struct csv::Reader<std::io::Stdin>
Surely, the R is not an R if you know what I mean but std::io::Stdin, that's why I've said that in the <...> brackets.
The key thing to understand here is that the generic arguments (R in this case) are always chosen by the caller. In your first example, the function is designed to work with any type that implements Read and therefore compiles.
The second, however, introduces a problem: According to the function signature, the caller should be able to get a Box<Reader<std::io::File>> if that’s what they want. But the function body can only provide a Box<Reader<Stdin>>.
dyn std::io::Read is a dynamically-sized type (DST for short), it is a type itself, but in order to use DST, it needs a special ?Sized bound. so by itself, the return type is already invalid, let alone the implementation returns a different type.
in your case, since you are returning a single concrete type (std::io::Stdin), you should just spell the type directly.
if, for some reason, you are not willing to specify the actual type, you can use existential type (i.e. impl std::io::Read), but not the trait object (i.e. dyn std::io::Read).
oh, I don't know what Reader<&[u8]> is,I assume you mean Cursor<&[u8]>, right? do you want something like this? note dyn SomeTrait is DST, but Box<dyn SomeTrait> is not.