I'd like to create a custom stream reader (e.g. my own BufReader). My function/struct must accept any kind of stream so I can then perform stream.read(buf). One more thing, I'm using async_std.
If you don't declare that your type parameter S is a reader, then you can't count on that inside the implementation. You need to add the appropriate trait bound like impl<S: Read> StreamReader<S>. (Not sure about the actual trait name, but if it's async stuff it's probably not exactly Read – you'll need to look it up in the relevant documentation.)
To elaborate on why this is: Rust traits are a contract between the implementation and the caller. The implementation says: "If your type satisfies this trait, I can do useful things with it". E.g. if your type is Read, then the implementation can .read() from it.
Then when you "instantiate" the generic (i.e. specify a concrete type in place of the type parameter), the compiler checks whether the type you are trying to substitute implements the required trait. If not, you get a compiler error – because how would then the impl use, for example, the methods of the trait on your type, if it didn't implement the trait?
Conversely, if there was no requirement to declare trait bounds, as is the case with C++ templates, for instance, then you could again pass any type at all even if it didn't have a .read() method. This leads to a situation where you can forget that your type needs to uphold some property and you silently assume it in the code, which will be rewarded with surprise compilation errors later, for instantiations that you otherwise intended to be correct and usable.
So basically, Rust's upfront checking saves you from bad surprises, by ensuring that once a generic function typechecks, so will all of its future instantiations that you wanted to allow in the first place.
Agreed, and while we're at style, I also prefer taking readers and writers by value, since (at least for std::io), there are Read impls for &mut R (and if there aren't in other libraries, there should be, probably). And not having to take a mutable borrow all the time is pretty convenient for writing as well as reading.