Why an immutable reference can work in match when mutable reference is required by function in Rust?

Viewed 99

Hi I'm currently reading The Rust Programming Language book. In error handling chapter I found this code works well:

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("hello.txt");

    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),
    };

    let mut s = String::new();

    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),
    }
}

However, after rewritting using ? operator, the code only works in this way:

fn read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("hello.txt")?;

    let mut s = String::new();

    f.read_to_string(&mut s)?;

    Ok(s)
}

Please note that f now become mutable! In the first version f is immutable. The definition of read_to_string is fn read_to_string(&mut self, buf: &mut String) -> Result<usize>, which requires a mutable self reference. But why the first version works without an compile time error here? f (self) is not mutable here!

1 Answers

In the first version, the first f is immutable, but then you shadow it and bind f mutably:

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("hello.txt"); // this is immutable

    let mut f = match f { ... } // this is mutable
}

The read_to_string function takes a mutable reference to self, so in both examples, f is required to be mutable.

Related