When you write a struct like, TtfDecode<R>, it means that R can be any type at all. When you define the impl block like impl<R: BufRead> TtfDecoder<R>, it means that R is any type that implements the BufRead trait. Note the word any. While the variable r is of type std::io::BufReader and hence compatible with R, it may not be the type specified by the caller of TtfDecoder::new. Note that the generic type is decided by the caller of the function. What you probably want is:
In cases like that it's usually good idea to explain what you expected to achieve.
Because it's very easy to say “what's wrong” (compiler did that pretty convincingly) but very hard to understand what you wanted to achieve without extra info.
pub struct TtfDecoder<R: Read> {
reader: BufReader<R>,
}
impl<R: Read> TtfDecoder<R> {
fn new(reader: R) -> Self {
let r = BufReader::new(reader);
Self { reader: r }
}
}
Try to explain what you want to achieve in plain English and then, 9 times out of 10, it would be easy to implement what you invented.
Just showing us something uncompileable written in Rust doesn't really help much: compiler can not userstand what you wrote, how can you be sure other people would be able to understand your intent?
Type parameters are outside of your control. The specific type of R will be chosen by the user of the struct, not by you, so you can't say R is a BufReader, because that would be a bug for TtfDecoder<File>, for example. Note that R is a single specific, but unknown at this point, type. It's not the same as Box<dyn Read> which allows multiple types with the same interface.
You can have reader: BufReader<R>. Or you can move new to impl block for TtfDecoder<BufReader<R>>.