Skip to content

Index chosen over IndexMut incorrectly, with a confusing error message. #75680

Closed
@smarnach

Description

@smarnach

Retrieving an element from a vector of mutable references works fine calling index_mut() directly

use std::ops::IndexMut;

fn explicit_trait_call(mut a: Vec<&mut i32>) {
    let _i: &mut i32 = *a.index_mut(0);
}

but fails when using supposedly equivalent indexing syntax:

fn indexing(mut a: Vec<&mut i32>) {
    let _i: &mut i32 = a[0];
}

(Playground)

The error message is rather surprising:

error[E0596]: cannot borrow data in an index of `std::vec::Vec<&mut i32>` as mutable
 --> src/lib.rs:4:24
  |
4 |     let _i: &mut i32 = a[0];
  |                        ^^^^ cannot borrow as mutable
  |
  = help: trait `IndexMut` is required to modify indexed content, but it is not implemented for `std::vec::Vec<&mut i32>`

It's clearly not true that IndexMut is not implemented for Vec, as evidenced by the first implementation.

The explicit trait call version only works because the explicit type annotation for _i triggers an implicit reborrow. My gut feeling is that the compiler is selecting Index instead of IndexMut here since the assignment looks like a move when not taking into account the implicit reborrow. I feel that the rejected code should be accepted. In any case, the error message should be fixed.

This post was inspired by a question of StackOverflow today, and I discussed this on the user forum as well.

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-bugCategory: This is a bug.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions