I'm getting an error trying to run this code:
use serde_json::{json, Map, Value};
fn get_json() -> Map<String, Value>{
let r = json!({
"x": "y"
});
let r = r.as_object().unwrap();
return r.clone();
}
fn main() {
let mut a = get_json();
let mut d: Map<String, Value> = Map::new();
let x = a["x"].as_str().unwrap();
a.insert("g".to_string(), Value::String("x".to_string()));
d.insert(x.to_string(), Value::Object(a));
}
Error:
cannot borrow `a` as mutable because it is also borrowed as immutable
mutable borrow occurs hererustcE0502
main.rs(14, 13): immutable borrow occurs here
main.rs(16, 14): immutable borrow later used here
I'm not even trying to borrow a, I'm only trying to insert something to it.
How about:
use serde_json::{json, Map, Value};
fn get_json() -> Map<String, Value> {
let r = json!({
"x": "y"
});
r.as_object().unwrap().clone()
}
fn main() {
let mut a = get_json();
a.insert("g".to_string(), Value::String("x".to_string()));
let d = Map::<String, Value>::from_iter(vec![(a["x"].to_string(), Value::Object(a))]);
}
Related
Full error:
--> src\readers.rs:10:30
|
5 | pub fn get_sequences(raw_sequences: &str) -> Result<Vec<Cow<[u8]>>, Error> {
| - let's call the lifetime of this reference `'1`
...
10 | while let Some(result) = reader.next() {
| ^^^^^^ `reader` was mutably borrowed here in the previous iteration of the loop
...
15 | Ok(sequences)
| ------------- returning this value requires that `reader` is borrowed for `'1`
Code:
pub fn get_sequences(raw_sequences: &str) -> Result<Vec<Cow<[u8]>>, Error> {
let bytes = raw_sequences.as_bytes();
let mut reader = Reader::new(BufReader::new(bytes));
let mut sequences: Vec<Cow<[u8]>> = vec![];
while let Some(result) = reader.next() {
let record = result?;
sequences.push(record.full_seq());
}
Ok(sequences)
}
I'm using the SeqIO crate (https://github.com/markschl/seq_io/tree/v0.3)
Honestly not sure how to fix this. Any help would be appreciated
the fix is change full_seq to owned_seq, and return Vec<Vec> instead of Vec<Cow<[u8]>>, the is because record do have a reference to reader, and full_seq return a Cow type that has implicit reference to record, thus it has reference to the reader which is a local variable
pub fn get_sequences(raw_sequences: &str) -> Result<Vec<Vec<u8>>, Error> {
let bytes = raw_sequences.as_bytes();
let mut reader = Reader::new(bytes);
let mut sequences = vec![];
while let Some(result) = reader.next() {
let record = result?;
sequences.push(record.owned_seq());
}
Ok(sequences)
}
I can't figure out how to get the following to work. I think I need the closure to borrow by &mut Vec, but I don't know how to express that. This is distilled from a larger function, but shows the same error.
fn main() {
let mut v = vec![0; 10];
let next = |i| (i + 1) % v.len();
v[next(1usize)] = 1;
v.push(13);
v[next(2usize)] = 1;
}
Error:
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> a.rs:9:5
|
5 | let next = |i| {
| --- immutable borrow occurs here
6 | (i + 1) % v.len()
| - first borrow occurs due to use of `v` in closure
...
9 | v[next(1usize)] = 1;
| ^ ---- immutable borrow later used here
| |
| mutable borrow occurs here
error: aborting due to previous error
If you really want to do it with a closure, you will have to pass the vector by parameter:
let next = |v: &Vec<_>, i| (i + 1) % v.len();
This makes the closure borrow per-call, rather than capture for the scope. You still need to separate the borrows, though:
let j = next(&v, 1usize);
v[j] = 1;
To make your life easier, you can put everything inside the closure instead:
let next = |v: &mut Vec<_>, i, x| {
let j = (i + 1) % v.len();
v[j] = x;
};
Which allows you to simply do:
next(&mut v, 1usize, 1);
next(&mut v, 2usize, 2);
// etc.
This pattern is useful for cases where you are writing a closure just for avoiding local code repetition (which I suspect is why you are asking given the comments).
Since the closure only needs the length of the Vec. Then instead, you can just get that prior to the closure. Then you avoid the whole borrowing issue, as the closure doesn't need to borrow v anymore.
fn main() {
let mut v = vec![0; 10];
let len = v.len();
let next = |i| (i + 1) % len;
v[next(1usize)] = 1;
}
Assuming your closure is not dependent on other things, then instead of a closure, you could define a trait with a method that does that.
For simplicity let's call the trait VecExt and the method set.
trait VecExt<T> {
fn set(&mut self, index: usize, value: T);
}
impl<T> VecExt<T> for Vec<T> {
fn set(&mut self, index: usize, value: T) {
let len = self.len();
self[(index + 1) % len] = value;
}
}
fn main() {
let mut v = vec![0; 10];
v.set(1, 1);
v.push(13);
v.set(2, 1);
}
A closure probably isn't the right tool for the job. The compiler is unhappy because your closure has taken a reference against your Vec, but then while that closure reference is still outstanding you're trying to mutate the Vec. Under Rust's borrow rules, that's not allowed.
The most straightforward approach would be storing your data inside a struct, and making next a member function. That way, there's no closure taking references; it can just check the length only when needed.
struct WrapVec<T>(Vec<T>);
impl<T> WrapVec<T> {
fn wrap_next(&mut self, index: usize) -> &mut T {
let index = (index + 1) % self.0.len();
&mut self.0[index]
}
}
fn main() {
let mut v = WrapVec(vec![0; 10]);
*v.wrap_next(1) = 1;
v.0.push(13);
*v.wrap_next(2) = 1;
}
If you want to be able to apply this function to any Vec, then you may find it useful to define a new trait. For example:
trait WrapNext<T> {
fn wrap_next(&mut self, index: usize) -> &mut T;
}
impl<T> WrapNext<T> for Vec<T> {
fn wrap_next(&mut self, index: usize) -> &mut T {
let index = (index + 1) % self.len();
&mut self[index]
}
}
fn main() {
let mut v = vec![0; 10];
*v.wrap_next(1) = 1;
v.push(13);
*v.wrap_next(2) = 1;
}
In addition to the other answers here, you can use a macro to scope v so you don't have to pass it in every call:
fn main() {
let mut v = vec![0; 10];
macro_rules! next {
// rule to get an index
($i: expr) => {
($i + 1) % v.len()
};
// rule to mutate the vector
($i: expr => $v: expr) => {{
let ind = next!($i);
v[ind] = $v;
}};
};
// get an index
let ind = next!(1usize);
// mutate the vector
v[ind] = 1;
v.push(13);
// or, with the mutation syntax
next!(2usize => 3);
println!("{:?}", v);
}
I am reading the official Rust Book and looking at listing 4-8 in Section 4.3.
The code looks like this:
fn first_word(s: &String) -> usize {
let bytes = s.as_bytes();
for (i, &item) in bytes.iter().enumerate() {
if item == b' ' {
return i;
}
}
s.len()
}
fn main() {
let mut s = String::from("hello world");
let word = first_word(&s);
s.clear();
}
This line:
let word = first_word(&s);
seems to borrow an immutable reference to s. (This is where I guess I'm wrong; I just don't know why.)
In the next line, we mutate s by calling the clear() method.
I was expecting the compiler to throw:
cannot borrow `s` as mutable because it is also borrowed as immutable
Why does this compile?
The string s is immutably borrowed for the duration of the call to first_word. As soon as the control is returned to main after first_word, the string is not considered borrowed anymore and can be mutated as you have observed.
If first_word were to return a &String which you extended the lifetime of by assigning it to a variable, then you would see the error you expected. E.g.
fn first_word(s: &String) -> &String {
&s
}
fn main() {
let mut s = String::from("hello world");
let word = first_word(&s);
s.clear();
}
cannot borrow s as mutable because it is also borrowed as immutable
https://rust.godbolt.org/z/cMVdVf
In that case, adding an extra scope would fix that:
fn main() {
let mut s = String::from("hello world");
{
let word = first_word(&s);
}
s.clear();
}
I have a function f that accepts two references, one mut and one not mut. I have values for f inside a HashMap:
use std::collections::HashMap;
fn f(a: &i32, b: &mut i32) {}
fn main() {
let mut map = HashMap::new();
map.insert("1", 1);
map.insert("2", 2);
{
let a: &i32 = map.get("1").unwrap();
println!("a: {}", a);
let b: &mut i32 = map.get_mut("2").unwrap();
println!("b: {}", b);
*b = 5;
}
println!("Results: {:?}", map)
}
This doesn't work because HashMap::get and HashMap::get_mut attempt to mutably borrow and immutably borrow at the same time:
error[E0502]: cannot borrow `map` as mutable because it is also borrowed as immutable
--> src/main.rs:15:27
|
12 | let a: &i32 = map.get("1").unwrap();
| --- immutable borrow occurs here
...
15 | let b: &mut i32 = map.get_mut("2").unwrap();
| ^^^ mutable borrow occurs here
...
18 | }
| - immutable borrow ends here
In my real code I'm using a large, complex structure instead of a i32 so it is not a good idea to clone it.
In fact, I'm borrowing two different things mutably/immutably, like:
struct HashMap {
a: i32,
b: i32,
}
let mut map = HashMap { a: 1, b: 2 };
let a = &map.a;
let b = &mut map.b;
Is there any way to explain to the compiler that this is actually safe code?
I see how it possible to solve in the concrete case with iter_mut:
{
let mut a: &i32 = unsafe { mem::uninitialized() };
let mut b: &mut i32 = unsafe { mem::uninitialized() };
for (k, mut v) in &mut map {
match *k {
"1" => {
a = v;
}
"2" => {
b = v;
}
_ => {}
}
}
f(a, b);
}
But this is slow in comparison with HashMap::get/get_mut
TL;DR: You will need to change the type of HashMap
When using a method, the compiler does not inspect the interior of a method, or perform any runtime simulation: it only bases its ownership/borrow-checking analysis on the signature of the method.
In your case, this means that:
using get will borrow the entire HashMap for as long as the reference lives,
using get_mut will mutably borrow the entire HashMap for as long as the reference lives.
And therefore, it is not possible with a HashMap<K, V> to obtain both a &V and &mut V at the same time.
The work-around, therefore, is to avoid the need for a &mut V entirely.
This can be accomplished by using Cell or RefCell:
Turn your HashMap into HashMap<K, RefCell<V>>,
Use get in both cases,
Use borrow() to get a reference and borrow_mut() to get a mutable reference.
use std::{cell::RefCell, collections::HashMap};
fn main() {
let mut map = HashMap::new();
map.insert("1", RefCell::new(1));
map.insert("2", RefCell::new(2));
{
let a = map.get("1").unwrap();
println!("a: {}", a.borrow());
let b = map.get("2").unwrap();
println!("b: {}", b.borrow());
*b.borrow_mut() = 5;
}
println!("Results: {:?}", map);
}
This will add a runtime check each time you call borrow() or borrow_mut(), and will panic if you ever attempt to use them incorrectly (if the two keys are equal, unlike your expectations).
As for using fields: this works because the compiler can reason about borrowing status on a per-field basis.
Something appears to have changed since the question was asked. In Rust 1.38.0 (possibly earlier), the following compiles and works:
use std::collections::HashMap;
fn f(a: &i32, b: &mut i32) {}
fn main() {
let mut map = HashMap::new();
map.insert("1", 1);
map.insert("2", 2);
let a: &i32 = map.get("1").unwrap();
println!("a: {}", a);
let b: &mut i32 = map.get_mut("2").unwrap();
println!("b: {}", b);
*b = 5;
println!("Results: {:?}", map)
}
playground
There is no need for RefCell, nor is there even a need for the inner scope.
I want to retrieve an element from a vector if a condition on that element is true.
fn draw() -> Option<String> {
let mut v: Vec<String> = vec!["foo".to_string()];
let t: Option<String>;
let o = v.last();
// t and v are actually a fields in a struct
// so their lifetimes will continue outside of draw().
match o {
Some(ref e) => {
if check(e) {
t = v.pop();
t.clone()
} else {
None
}
}
None => None,
}
}
fn check(e: &String) -> bool {
true
}
fn main() {}
playground
This results in the error:
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> src/main.rs:12:21
|
4 | let o = v.last();
| - immutable borrow occurs here
...
12 | t = v.pop();
| ^ mutable borrow occurs here
...
20 | }
| - immutable borrow ends here
Which I sort of understand, however I don't see a way to end the borrow (without using clone()).
Borrows are lexical, so v has the life-time of the whole function. If one can reduce the scope, one can use last() and pop(). One way to do this is a functional-style map:
let mut v: Vec<String> = vec!["foo".to_string()];
if v.last().map_or(false, check) {
v.pop()
} else {
None
}