Skip to content

IndexMut incorrectly chosen instead of Index #28935

Closed
@wthrowe

Description

@wthrowe
Contributor
use std::ops::{Index, IndexMut};

struct S;

impl S { fn foo(&self) -> i32 { 0 } }

impl Index<usize> for S {
    type Output = S;
    fn index(&self, _: usize) -> &S { self }
}

impl IndexMut<usize> for S {
    fn index_mut(&mut self, _: usize) -> &mut S { self }
}

fn main() {
    let s = S;
    let _ = &mut s.foo(); // OK
    let _ = &mut (&s[0]).foo(); // OK
    let _ = &mut s[0].foo(); // error: cannot borrow immutable local variable `s` as mutable                                                                   
}

The whole example compiles it the IndexMut implementation is removed.

Activity

gwillen

gwillen commented on Dec 9, 2015

@gwillen
Contributor

I'm also running into something that appears to be this issue. I'm indexing a Vec, so the implementation of IndexMut is not under my control. I can try to make a reduced example using Vec if it would be helpful. EDIT: oh, it seems that 29869 already contains such an example.

added
T-langRelevant to the language team
and removed on Mar 24, 2017
PeterHatch

PeterHatch commented on Oct 12, 2017

@PeterHatch

Just wanted to note that I encountered this bug.

shepmaster

shepmaster commented on Oct 25, 2018

@shepmaster
Member

This came up on Stack Overflow. A simplified example:

use std::cell::RefCell;

fn f(v: Vec<RefCell<u8>>) {
   let _t = &mut *v[0].borrow_mut();
}

fn main() {}
error[E0596]: cannot borrow immutable argument `v` as mutable
 --> src/main.rs:4:20
  |
3 | fn f(v: Vec<RefCell<u8>>) {
  |      - consider changing this to `mut v`
4 |     let _t = &mut *v[0].borrow_mut();
  |                    ^ cannot borrow mutably

Workarounds include:

  1. Using extra braces:

    fn f(v: Vec<RefCell<u8>>) {
        let _t = &mut *{ v[0].borrow_mut() };
    }
  2. Calling Index::index explicitly:

    fn f(v: Vec<RefCell<u8>>) {
        use std::ops::Index;
        let _t = &mut *v.index(0).borrow_mut();
    }
  3. Calling RefCell::borrow explicitly:

    fn f(v: Vec<RefCell<u8>>) {
        let _t = &mut *RefCell::borrow_mut(&v[0]);
    }
jackh726

jackh726 commented on Jan 29, 2022

@jackh726
Member

This compiles now. Marking as needs-test (unsure if there is one that covers this already)

9 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-inferenceArea: Type inferenceA-trait-systemArea: Trait systemC-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

      Development

      Participants

      @steveklabnik@shepmaster@gwillen@wthrowe@jonas-schievink

      Issue actions

        IndexMut incorrectly chosen instead of Index · Issue #28935 · rust-lang/rust