Indexing syntax borrow checking should work as with functions

I often want to access elements in a slice from the end:

&mut slice[ slice.len() - index ]

However, borrow checker complains:

cannot borrow slice as immutable because it is also borrowed as mutable

If I use a method (IndexMut::index_mut or .get_mut(slice.len() - index).unwrap()), then everything is fine.

Therefore, I think the indexing syntax should work the same.

1 Like

This is "two phase borrows," if you want the key phrase to search for. It is definitely odd that it doesn't apply here to indexing syntax.


This compiles successfully in the current stable Rust toolchain (playground):

pub fn foo<T>(slice: &mut [T], index: usize) -> &mut T {
    &mut slice[slice.len() - index]

Can you give a complete example that does not compile?

1 Like

This issue is related:

A &mut [T] looks to work but a Vec<T> fails (playground)

pub fn foo<T>(slice: &mut Vec<T>, index: usize) -> &mut T {
    // let slice : &mut [T] = slice; 
    &mut slice[slice.len() - index]

It appears two phase borrows don't apply when DerefMut is involved, even for methods instead of indexing.

Which makes sense: normally a two-phase borrow needs to be "activated" only immediately before the method is called, but with DerefMut involved the borrow must be mutable straight away to pass to deref_mut, before the other arguments are evaluated.

(But apparently Box behaves differently, probably because dereferencing a Box doesn't use DerefMut.)

1 Like

I made a little crate for doing that a few years back that you could play with. It would allow your example as &mut slice.rev()[index] (assuming you meant &mut slice[slice.len()-(index+1)] in your example, so that index == 0 isn't out-of-bounds).


Arrays (as well as Vec, mentioned by Jon-Davis) might be treated differently than slices: Playground