I found some code I don't understand. The function below takes a "Read" argument, but then it calls
read_i32, which doesn't seem to be defined as a function on the Read trait. Instead, it's on some Trait called byteorder::ReadBytesExt. I don't understand the relationship between ReadBytesExt and Read. How can one be sure that the argument, a "Read" is also a "ReadBytesExt"?
pub fn read_from<R: Read>(read: &mut R) -> std::io::Result
let data = SomeStruct::make();
data.level = read.read_i32::()?;
ReadBytesExt has a blanket impl for any
T that implements
Read. That means any type that implements
Read already has an implementation of the extension trait, so there's no reason to require an additional bound.
Note that the extension trait does still need to be imported into that scope to be able to call the methods on the extension trait though.
That sounds like
ReadBytesExt is a supertrait of
Read: you must implement
ReadBytesExt in order to implement
Read. I think it would be more clear to say:
any type that implements
Read will also implement the extension trait
That way, the reader can easily understand that the extension trait will be implemented automatically.
Thanks! I edited it for clarity
So in this case
ReadBytesExt provides an implementation for all implementations of
Read. So is there some reason why the object that is passed isn't require it to be of trait
ReadBytesExt instead of
Read? Would this work?
It might; but I think in that case, it would require the caller to import the
ReadBytesExt trait into the code that calls
read_from. This way,
ReadBytesExt is only present inside the
The reason it isn’t required to explicitly say
ReadBytesExt in the bound is because it’s impossible for any type that implements
Read to not implement
ReadBytesExt. Requiring you to use
R: Read + ReadBytesExt as the bound on
R would severely limit the usefulness of extension traits, in addition to just being redundant.
I’m not sure off the top of my head if the reverse also works, but in my opinion only using the extension trait as your bound would look sort of weird even if it does work.
Read is a supertrait here, so it would work (and doesn't seem that weird to me, but ).