Beginner - Sub? Trait

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 read_from scope

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 :person_shrugging:).

1 Like