Are `&a[..]` and `a` of the same type?

Hi, I'm confused about the following code. If I change &a[..] to a, rustc would complain cannot borrow a as mutable, as it is not declared as mutable.
In my mind, both &a[..] and a are of type &[u8].
BTW, any fast tool to check type of an expression rather than running rustc? I think that'll be suitable for studying rust's strong-n-complicated type system.

use std::io::BufRead;

fn main() {
let aa = String::from("hello\nworld");
let a = aa.as_bytes();
let mut buf = String::new();
assert!(match (&a[..]).read_line(&mut buf) {
    Ok(6) => true,
    Ok(e) => {
        println!("got OK({})", e);
        false
    }
    Err(e) => {
        println!("got Err({})", e);
        false
    }
});
}

They are the same type, &[u8], but &a[..] is a temporary in the expression which can implicitly be mutated. BufRead needs &mut self, which in this case works out to &mut &[u8]. The actual data is still immutable, but when you read a slice, it will be reduced to a slice of the remainder.

It should work with a alone if you declare it let mut a = ..., or you can also force it into a temporary with a block expression, {a}.read_line(&mut buf).

3 Likes

Thank you for the clarification. So it's actually the pointer moving forward as I read.
And a in let mut a= is actually a mut & rather than &mut, which I just confused up.

1 Like

In Rust references are type just like any other types. The type &'a [u8] implements trait BufRead and since the BufRead::read_line() takes &mut Self, you need to pass &mut &[u8] to this method.

Thanks, and the key is that a [u8] slice is actually a &mut &[u8], in which the mut is a little surprising to me. Once known it's natural though.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.