1

I have a reference to an object (&T) and &mut ((&T).method1().method2().iter()) where iter() returns an owned value. However, this produces an error that it tries to mutably borrow &T.

This simple example is working:

struct A;

impl A {
    fn get_array(&self) -> Vec<u32> {
        vec![1,2,3]
    }
}


fn main() {
    let a = &A{};
    for (_q_name, q_iter) in &mut [
        (
            "iterator1",
            &mut (a.get_array().iter()) // mutably borrow iterator
                as &mut dyn std::iter::Iterator<Item = &u32>,
        ),
    ] {

        for n in  q_iter {
            println!("{}", n);
        }
    }
}

This does not:

use serde_json::{json,Value};

fn main() {
    let obj:&Value = &json!({
        "key": [1,2,3],
    });


    let mut it = obj["key"].as_array().unwrap().iter();
    for (_q_name, q_iter) in &mut [
        (
            "iterator1",
//          &mut (obj["key"].as_array().unwrap().iter())      // error
//          &mut it                                           // ok
                as &mut dyn std::iter::Iterator<Item = &Value>,
        ),
    ] {

        for n in  q_iter {
            println!("{}", n);
        }
    }

}

error[E0596]: cannot borrow `*obj` as mutable, as it is behind a `&` reference
  --> src/main.rs:14:16
   |
14 |          &mut (obj["key"].as_array().unwrap().iter())      // error
   |                ^^^ `obj` is a `&` reference, so the data it refers to cannot be borrowed as mutable
help: consider changing this to be a mutable reference
   |
5  |     let obj:&Value = &mut json!({
6  |         "key": [1,2,3],
7  |     });
   |

I just want my iterator mutable, not obj.

If I cannot mutably borrow an owned value, why is the first example working?

Playground

Edit: removed wrong code

mq7
  • 1,125
  • 2
  • 11
  • 21
  • Do you really need an array of tuples to iterate over? At least in the MCVE? – Michail Mar 16 '19 at 22:38
  • I included the tuple because the behavior with tuples was different. For example, `for (a, mut b) in &mut[..]` produces new errors. – mq7 Mar 16 '19 at 22:42
  • 1
    This is an old and somewhat obscure compiler bug. The linked Q&A found the same thing. The same thing they did will also work here (wrap the expression in `{}` instead of `()`). You could also write something like `&mut (&obj["key"]).as_array().unwrap().iter()`; the shared reference lets the compiler know that it can use `Index` instead of `IndexMut`. – trent Mar 17 '19 at 01:39
  • 1
    Credit for figuring it out should also go to @Michail for workshopping the example in chat. – trent Mar 17 '19 at 01:49

0 Answers0