Method cannot be invoked on a trait object until its supertrait is brought into scoope

I was trying to call bytes on a BufRead trait object and initially received the error that the method couldn't be invoked because bytes has Sized requirement. However, if std::io::Read is brought into scope, the call to bytes goes through. I understand that bytes is a method of the Read trait, so having the use statement for it makes sense, but I'm having a bit of trouble understanding how adding the import seems to suddenly make a trait object Sized.

I did a bit of research and my intuition is that perhaps the compiler doesn't create the concrete method to dispatch to without the import of Read, but I don't have the knowledge to say for certain if that's the case or not. Could anyone give me some more insight as to what's happening here? Thanks!

Hmm, that error message is quite bad at providing context.

It doesn't make the trait object Sized, but it has an effect on method resolution.

Trait method on trait objects act like inherent methods in some ways. One of those ways is that method resolution with consider them even if the trait is not in scope. (The idea being this lets you use the trait methods via trait object without bringing the trait into scope, which usually works, but didn't in this case.)

So when you haven't brought Read into scope, method resolution does find and try to use

<dyn BufRead>::read

But as the error says, that has a where Self: Sized requirement, so that fails. In contrast, when you bring the trait into scope, method resolution will consider methods of the trait in the usual fashion -- not just as if they were inherent methods of dyn BufRead specifically -- and will instead first find and select...

// if you have `br: &mut dyn BufRead` and run `br.read()`
<&mut dyn BufRead as Read>::read

// if you have `br: Box<dyn BufRead>` and run `br.read()`
<Box<dyn BufRead as Read>>::read

...due to the candidate list order (and the fact that there are blanket implementations for &mut R and Box<R> where R: Read + ?Sized). If you do something like

let _ = (*br).read();

you should get the original error again (minus the suggestion to import the trait).

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.