rust

rust `&mut buffer[..]` vs just `&mut buffer`


In the Rust documentation for std::io::Read::read() I came across this example:

fn main() -> io::Result<()> {
    let mut f = File::open("foo.txt")?;
    let mut buffer = [0; 10];

    // read up to 10 bytes
    let n = f.read(&mut buffer[..])?;
    // Is there any difference between the previous line and the next one?
    // let n = f.read(&mut buffer)?;

    println!("The bytes: {:?}", &buffer[..n]);
    Ok(())
}

You can see let n = f.read(&mut buffer[..])?;, buffer[ .. ] contains all values from start to end and then we have a mutable reference to them.

Would it make any difference if I would write let n = f.read(&mut buffer)?; instead?

I tried it and to me it seems the same, but I wondered why authors used &mut buffer[..], am I missing something?


Solution

  • The types are different:

    buffer [u8; 10]
    &mut buffer &mut [u8; 10]
    &mut buffer[..] &mut [u8]
    buffer.as_mut_slice() &mut [u8]

    So why can a function that wants a &mut [u8] argument take a &mut buffer?

    The magic here is in automatic type coercion, which states that a &mut [u8; 10] can be coerced into a &mut [u8] automatically.

    Functionally, there is no difference. It's like the difference between an explicit and implicit cast. &mut [..] converts to a slice explicitly and no coercion happens, &mut does not convert explicitly and an implicit coercion happens. The resulting machine code will be identical.

    For more information about the difference between [u8; 10] and [u8], read What is the difference between a slice and an array?.

    So writing f.read(&mut buffer) is perfectly fine and, in my opinion, preferred to f.read(&mut buffer[..]). It's just easier to read.

    EDIT: @ChayimFriedman pointed out that coercion does not always happen automatically, which is correct. Coercion can only happen at coercion sites. The relevant coercion site for this example is using a variable as the 'argument for a function call'. If you have a situation where no coercion site is present, then the explicit conversion might indeed be required.