foo[i] is desugared to *Index::index(foo, i). I.e., there's an implicit dereference, so you don't have to write that out. Having to write *some_slice[i] += 1 would be way more annoying.
It's to differentiate between Index and IndexMut - &x[y] uses Index but &mut x[y] uses IndexMut, and Rust needs to know which one to call. There is one exception to this rule, and that is when the type implements Copy, and you can write x[y] which is equivalent to *&x[y] (it uses Index).
This is for consistency with other kinds of indexing. For example, if you have a Vec<i32>, you wouldn't want the_vector[5] to give you a reference, instead you want it to give you an integer. So just like the_vector[5] results in a i32 without the reference, x[..] will give you a str.