Mutable borrow occurs here [E0502] - rust

How can I correct this behavior ?
P.S Now I am trying to implement a search for the number of page_faults when using the FIFO algorithm
fn page_fault(capacity: i32, n: i32, pages: &[i32]) -> i32 {
let mut s: HashSet<i32> = HashSet::new();
let mut indexes: VecDeque<i32> = VecDeque::new();
let mut page_faults: i32 = 0;
for i in 0..n {
if (s.len() as i32) < capacity {
if s.contains(&pages[(i) as usize]) {
s.insert(pages[(i) as usize]);
page_faults += 1;
indexes.insert(i as usize, pages[(i) as usize])
}
}
else {
if s.contains(&pages[(i) as usize]) {
let val = indexes.front();
indexes.pop_front();
s.remove(&val.unwrap());
s.insert(pages[(i) as usize]);
indexes.push_back(pages[(i) as usize]);
page_faults += 1;
}
}
}
return page_faults;
}
Terminal:
let val = indexes.front();
--------------- immutable borrow occurs here
indexes.pop_front();
^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
s.remove(&val.unwrap());
--- immutable borrow later used here

Calling indexes.front() seems redundant to me. You can simply use the result of indexes.pop_front() and assign it to a variable. So you can replace these two lines:
let val = indexes.front();
indexes.pop_front();
With this line:
let val = indexes.pop_front();

When calling indexes.front you are keeping a reference to it (&self), it can be easily solved by unwraping inmediatly and dereferencing it so the i32 is copied. Then the reference is freed.
use std::collections::VecDeque;
use std::collections::HashSet;
fn page_fault(capacity: i32, n: i32, pages: &[i32]) -> i32 {
let mut s: HashSet<i32> = HashSet::new();
let mut indexes: VecDeque<i32> = VecDeque::new();
let mut page_faults: i32 = 0;
for i in 0..n {
if (s.len() as i32) < capacity {
if s.contains(&pages[(i) as usize]) {
s.insert(pages[(i) as usize]);
page_faults += 1;
indexes.insert(i as usize, pages[(i) as usize])
}
}
else {
if s.contains(&pages[(i) as usize]) {
let val = *indexes.front().unwrap();
indexes.pop_front();
s.remove(&val);
s.insert(pages[(i) as usize]);
indexes.push_back(pages[(i) as usize]);
page_faults += 1;
}
}
}
return page_faults;
}
Playground

Related

How to traverse and consume a vector in given order? [duplicate]

For example, I have a Vec<String> and an array storing indexes.
let src = vec!["a".to_string(), "b".to_string(), "c".to_string()];
let idx_arr = [2_usize, 0, 1];
The indexes stored in idx_arr comes from the range 0..src.len(), without repetition or omission.
I want to move the elements in src to another container in the given order, until the vector is completely consumed. For example,
let iter = into_iter_in_order(src, &idx_arr);
for s in iter {
// s: String
}
// or
consume_vec_in_order(src, &idx_arr, |s| {
// s: String
});
If the type of src can be changed to Vec<Option<String>>, things will be much easier, just use src[i].take(). However, it cannot.
Edit:
"Another container" refers to any container, such as a queue or hash set. Reordering in place is not the answer to the problem. It introduces the extra time cost of O(n). The ideal method should be 0-cost.
Not sure if my algorithm satisfies your requirements but here I have an algorithm that can consume the provided vector in-order without initializing a new temporary vector, which is more efficient for a memory.
fn main() {
let src = &mut vec!["a".to_string(), "b".to_string(), "c".to_string(), "d".to_string()];
let idx_arr = [2_usize, 3, 1, 0];
consume_vector_in_order(src, idx_arr.to_vec());
println!("{:?}", src); // d , c , a , b
}
// In-place consume vector in order
fn consume_vector_in_order<T>(v: &mut Vec<T>, inds: Vec<usize>) -> &mut Vec<T>
where
T: Default,
{
let mut i: usize = 0;
let mut temp_inds = inds.to_vec();
while i < inds.to_vec().len() {
let s_index = temp_inds[i];
if s_index != i {
let new_index = temp_inds[s_index];
temp_inds.swap(s_index, new_index);
v.swap(s_index, new_index);
} else {
i += 1;
}
}
v
}
You can use the technique found in How to sort a Vec by indices? (using my answer in particular) since that can reorder the data in-place from the indices, and then its just simple iteration:
fn consume_vec_in_order<T>(mut vec: Vec<T>, order: &[usize], mut cb: impl FnMut(T)) {
sort_by_indices(&mut vec, order.to_owned());
for elem in vec {
cb(elem);
}
}
Full example available on the playground.
Edit:
An ideal method, but needs to access unstable features and functions not exposed by the standard library.
use std::alloc::{Allocator, RawVec};
use std::marker::PhantomData;
use std::mem::{self, ManuallyDrop};
use std::ptr::{self, NonNull};
#[inline]
unsafe fn into_iter_in_order<'a, T, A: Allocator>(
vec: Vec<T, A>,
order: &'a [usize],
) -> IntoIter<'a, T, A> {
unsafe {
let mut vec = ManuallyDrop::new(vec);
let cap = vec.capacity();
let alloc = ManuallyDrop::new(ptr::read(vec.allocator()));
let ptr = order.as_ptr();
let end = ptr.add(order.len());
IntoIter {
buf: NonNull::new_unchecked(vec.as_mut_ptr()),
_marker_1: PhantomData,
cap,
alloc,
ptr,
end,
_marker_2: PhantomData,
}
}
}
struct IntoIter<'a, T, A: Allocator> {
buf: NonNull<T>,
_marker_1: PhantomData<T>,
cap: usize,
alloc: ManuallyDrop<A>,
ptr: *const usize,
end: *const usize,
_marker_2: PhantomData<&'a usize>,
}
impl<T, A: Allocator> Iterator for IntoIter<T, A> {
type Item = T;
#[inline]
fn next(&mut self) -> Option<T> {
if self.ptr == self.end {
None
} else {
let idx = unsafe { *self.ptr };
self.ptr = unsafe { self.ptr.add(1) };
if T::IS_ZST {
Some(unsafe { mem::zeroed() })
} else {
Some(unsafe { ptr::read(self.buf.as_ptr().add(idx)) })
}
}
}
}
impl<#[may_dangle] T, A: Allocator> Drop for IntoIter<T, A> {
fn drop(&mut self) {
struct DropGuard<'a, T, A: Allocator>(&'a mut IntoIter<T, A>);
impl<T, A: Allocator> Drop for DropGuard<'_, T, A> {
fn drop(&mut self) {
unsafe {
// `IntoIter::alloc` is not used anymore after this and will be dropped by RawVec
let alloc = ManuallyDrop::take(&mut self.0.alloc);
// RawVec handles deallocation
let _ = RawVec::from_raw_parts_in(self.0.buf.as_ptr(), self.0.cap, alloc);
}
}
}
let guard = DropGuard(self);
// destroy the remaining elements
unsafe {
while self.ptr != self.end {
let idx = *self.ptr;
self.ptr = self.ptr.add(1);
let p = if T::IS_ZST {
self.buf.as_ptr().wrapping_byte_add(idx)
} else {
self.buf.as_ptr().add(idx)
};
ptr::drop_in_place(p);
}
}
// now `guard` will be dropped and do the rest
}
}
Example:
let src = vec![
"0".to_string(),
"1".to_string(),
"2".to_string(),
"3".to_string(),
"4".to_string(),
];
let mut dst = vec![];
let iter = unsafe { into_iter_in_order(src, &[2, 1, 3, 0, 4]) };
for s in iter {
dst.push(s);
}
assert_eq!(dst, vec!["2", "1", "3", "0", "4"]);
My previous answer:
use std::mem;
use std::ptr;
pub unsafe fn consume_vec_in_order<T>(vec: Vec<T>, order: &[usize], mut cb: impl FnMut(T)) {
// Check whether `order` contains all numbers in 0..len without repetition
// or omission.
if cfg!(debug_assertions) {
use std::collections::HashSet;
let n = order.len();
if n != vec.len() {
panic!("The length of `order` is not equal to that of `vec`.");
}
let mut set = HashSet::<usize>::new();
for &idx in order {
if idx >= n {
panic!("`{idx}` in the `order` is out of range (0..{n}).");
} else if set.contains(&idx) {
panic!("`order` contains the repeated element `{idx}`");
} else {
set.insert(idx);
}
}
}
unsafe {
for &idx in order {
let s = ptr::read(vec.get_unchecked(idx));
cb(s);
}
vec.set_len(0);
}
}
Example:
let src = vec![
"0".to_string(),
"1".to_string(),
"2".to_string(),
"3".to_string(),
"4".to_string(),
];
let mut dst = vec![];
consume_vec_in_order(
src,
&[2, 1, 3, 0, 4],
|elem| dst.push(elem),
);
assert_eq!(dst, vec!["2", "1", "3", "0", "4"]);

Rust trait object in tuple --- expected trait object, found type

I have been reading chapter 17 in The Rust Programming Language and I have been trying to use trait objects in my code.
Could someone please explain why the function test2 does not compile while the others do?
trait Print {
fn print(&self) -> String;
}
impl Print for i32 {
fn print(&self) -> String {
return format!("{}", &self);
}
}
impl Print for &str {
fn print(&self) -> String {
return format!("'{}'", &self);
}
}
pub fn test1() {
let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
let bxx = Box::new(0);
let idx = 1;
v.push((idx, bxx));
for (idx, val) in &v {
println!("{} - {}", idx, val.print());
}
}
pub fn test2() {
let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
let bxx = Box::new(0);
let idx = 2;
let t = (idx, bxx);
v.push(t);
for (idx, val) in &v {
println!("{} - {}", idx, val.print());
}
}
pub fn test3() {
let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
v.push((3, Box::new("a")));
for (idx, val) in &v {
println!("{} - {}", idx, val.print());
}
}
fn main() {
test1();
test2();
test3();
}
playground
By default when boxing it is gonna take as a box of the espeficit type you are boxing. In your case would be Box<i32>. If you annotate the type specifically then it works:
pub fn test2() {
let mut v: Vec<(usize, Box<dyn Print>)> = Vec::new();
let bxx: Box<dyn Print> = Box::new(0);
let idx = 2;
let t = (idx, bxx);
v.push(t);
for (idx, val) in &v {
println!("{} - {}", idx, val.print());
}
}
Playground

Mutable borrow inside loop

I have a vector of tuples, each containing two strings. I want to transfer (one of) the two strings as a mutable reference into a hashmap. The other string is also transferred, but does not have to be mutable. The background is that I want to overwrite one string with the value of the other one later.
Given the following code:
use std::collections::HashMap;
fn main() {
let mut foo = String::from("foo");
let mut bar = String::from("bar");
let mut v = vec![(foo, &mut bar)];
let mut counter: HashMap<&str, (&str, &mut String, u8)> = HashMap::new();
create_counter(&mut v, &mut counter);
}
fn create_counter<'a>(
rows: &'a mut Vec<(String, &'a mut String)>,
counter: &mut HashMap<&'a str, (&'a str, &'a mut String, u8)>,
) {
let mut skip_count = 0;
let len = rows.len();
for i in 0..len {
if i == len - 1 {
break;
}
if skip_count > 0 {
skip_count -= 1;
continue;
}
let r = rows[i..i + 3].as_mut();
if r[0].0 == r[1].0 && r[0].1 != r[1].1 {
if r.len() == 2 || r[0].0 != r[2].0 {
counter.entry(&r[0].0).or_insert((r[1].1, &mut r[0].1, 0)).2 += 1;
skip_count = 1;
} else {
skip_count = 2;
}
}
}
}
Unfortunately the borrow checker does not allow this and gives me two error messages:
cannot borrow `*rows` as mutable more than once at a time
cannot borrow `r[_].1` as mutable because it is also borrowed as immutable
I understand the problem, but unfortunately I have no idea how best to solve it.
Can someone please help me to solve these two problems?
Playground Link

Solving shuffle the array problem on leetcode in Rust

fn shuffle(nums: Vec<i32>, n: i32) -> Vec<i32> {
let mut res: Vec<i32>;
let mut i = 0;
while i < n {
res.push(nums[i]);
res.push(nums[n + i]);
i += 1;
}
res
}
When I try to index the nums array to get a value at [i], I get this error:
the type [i32] cannot be indexed by i32
the trait SliceIndex<[i32]> is not implemented for i32
required because of the requirements on the impl of Index<i32> for Vec<i32>
Any ideas how to solve this?
You can only index Vec using usizes, so you have to cast your i32s to usizes in order to index into nums:
fn shuffle(nums: Vec<i32>, n: i32) -> Vec<i32> {
let mut res = Vec::new();
let mut i = 0;
while i < n {
res.push(nums[i as usize]);
res.push(nums[(n + i) as usize]);
i += 1;
}
res
}
playground

error: non-scalar cast: `core::option::Option<i32>` as `usize`

I am new to Rust. My code is given below:
use std::*;
fn DFS(A: i32, grid: &mut [[i32; 500]; 500], visited: &mut [i32; 500]) -> (usize, usize) {
let mut s = Vec::new();
s.push(A);
visited[A as usize] = 1;
let mut flag;
let mut max_height = 0;
let mut ans_vertex: usize = A as usize;
let mut x;
'outer: while let Some(top) = s.pop() {
s.push(top);
x = top as usize;
flag = 0;
'inner: for i in 1..500 {
if visited[grid[x][i] as usize] == 0 && grid[x][i] != 0 {
flag = 1;
s.push(grid[x][i]);
visited[grid[x][i] as usize] = 1;
break 'outer;
}
}
if s.len() > max_height {
max_height = s.len();
ans_vertex = s.pop() as usize;
}
if flag != 0 {
s.pop();
}
}
println!("{}, {}", ans_vertex, max_height);
return (ans_vertex, max_height);
}
fn fc(grid: &mut [[i32; 500]; 500]) {
for i in 1..500 {
for j in 1..500 {
grid[i][j] = 0;
}
}
grid[1][2] = 1;
grid[2][1] = 1;
grid[2][3] = 1;
grid[3][2] = 1;
grid[3][4] = 1;
grid[4][3] = 1;
}
fn main() {
let mut visited: [i32; 500] = [0; 500];
let mut grid: [[i32; 500]; 500] = [[0; 500]; 500];
fc(&mut grid);
let B = DFS(1, &mut grid, &mut visited);
println!("{}", B.0);
}
I already tried changing usize to u32 and other types, but I'm not getting any results. When I run rustc newdia.rs, it shows:
newdia.rs:26:17: 26:33 error: non-scalar cast: `core::option::Option<i32>` as `usize`
newdia.rs:26 ans_vertex = s.pop() as usize;
^~~~~~~~~~~~~~~~
error: aborting due to previous error
Vec::pop() returns an Option<T> because if the Vec is empty, there's no value present to pop. If you're sure your Vec contains atleast 1 value before you call Vec::pop(), you can use Option::unwrap(), which will convert your Option<i32> to i32 (and panic if Vec::pop returned None because the Vec was empty).
ans_vertex = s.pop().unwrap() as usize;
You can also choose to handle the cases differently using match or if let:
if let Some(popped) = s.pop() {
// Successfully popped `popped`. `popped` here is an i32.
} else {
// `s` was empty.
}

Resources