Why call Read::read_to_end gives "method not found", but io::copy works

    let file = File::open(path).expect("the path to reader does not exist");
    let mut dec = FrameDecoder::new(file);
    let mut buf = Vec::<u8>::new();
    std::io::copy(&mut dec, &mut buf).expect("decode failed"); // works
    dec.read_to_end(&mut buf).unwrap(); // method not found in `snap::read::FrameDecoder<std::fs::File>`

FrameDecoder did implement Read:

    impl<R: io::Read> io::Read for FrameDecoder<R> {
      // ...
    }

Is the Read trait in scope?

I actually don't know what does "in scope" mean, could you explain? Thanks!

Do you have a use statement?

use std::io::Read;
1 Like

It worked, thanks!
Do you have reference to why I need use std::io::Read; Just want to understand why it worked.

It's because the read_to_end method is defined on the trait, and not on FrameDecoder.

I thought because the source code of FrameDecoder have use std::io::Read, so I would get use std::io::Read for free, without importing it. Is it not how Rust works?

No, you need to import the trait that defines a method if you wish to use that method. This is because there might be multiple traits that define a read_to_end method, and this allows the compiler to tell which one to use.

1 Like

Ah, interesting to know, thank you!

E.g. otherwise you risk the situation where you later add a dependency containing this, and having your code stopping to compile, because now there are suddenly two read_to_end methods on FrameDecoder.

// in some third party crate

trait MyTrait {
    fn read_to_end(&mut self, buf: &mut String) -> io::Result<usize>;
}
impl MyTrait for FrameDecoder {
    fn read_to_end(&mut self, buf: &mut String) -> io::Result<usize> { todo!() }
}

Some crates actually use this technique to add methods to existing types. An example of this is itertools, which adds methods to all iterators. You can only use these methods if you import the extension trait.

1 Like