It’s more than that though. Even if your signature was:
fn read(&mut self, len: usize) -> io::Result<Vec<u8>>
then you’d be forcing an allocation on the caller, which has significant implications for performance. For example, if I don’t need to hold the entire contents of my underlying reader in memory at once, then I can allocate a single buffer and process the input incrementally:
let mut buf = vec![0; 1024]; // process 1024 bytes at a time
loop {
buf.clear();
let n = try!(reader.read(&mut buf));
if n == 0 { // EOF
break;
}
let block = &buf[0..n];
// do something with the bytes in `block` ...
}
If read always returned a Vec, then I wouldn’t be able to amortize the allocation of buf like in the above code. Instead, I’d be forced to create a new one for every call to read.