What is count as moving the value in rust? - rust

I am trying to implement a function for converting BigInt to vector of u8 in Rust.
`
fn BigInt_to_Vector(x: BigInt) -> Vec<u8> {
let mut v : Vec<u8> = vec![];
let mut n = x.clone();
let byte : BigInt = BigInt::from(256);
while(x > BigInt::from(0)) {
v.push((n%byte).to_u8().unwrap());
n = n/byte;
}
v
}
`
I am encountering the following error :
`
let byte : BigInt = BigInt::from(256);
| ---- move occurs because `byte` has type `BigInt`, which does not implement the `Copy` trait
v.push((n%byte).to_u8().unwrap());
| ---- value moved here
n = n/byte;
| ^^^^ value used here after move
`
I know this error can be directly dealt by deriving the value BigInt::from(256) every time instead of using variable byte (for example, n%byte becomes n%BigInt::from(256)).
But I am unable to understand the reason behind the error even after doing some internet search. And finally, if I want to keep using byte variable, what measures should I take ?

The solution here is borrow n and byte where you don't want them moved:
fn BigInt_to_Vector(x: BigInt) -> Vec<u8> {
let mut v: Vec<u8> = vec![];
let mut n = x.clone();
let byte = BigInt::from(256);
let zero = BigInt::from(0);
while x > zero {
// Borrow `n` and `byte` for the rem op so they aren't moved
v.push((&n % &byte).to_u8().unwrap());
// Borrow `byte` for the div op so it isn't moved
// It's okay if `n` is moved here
n = n / &byte;
}
v
}

Related

Peek iterator inside `for` loop

I'm trying to peek at the char in-front of my current location whilst iterating over a &str.
let myStr = "12345";
let mut iter = myStr.chars().peekable();
for c in iter {
let current: char = c;
let next: char = *iter.peek().unwrap_or(&'∅');
}
I will be passing this char into a method down the line. However, even this MRE produces a borrow after move error that I'm not sure how to get past.
error[E0382]: borrow of moved value: `iter`
--> src/lib.rs:7:27
|
4 | let mut iter = myStr.chars().peekable();
| -------- move occurs because `iter` has type `Peekable<Chars<'_>>`, which does not implement the `Copy` trait
5 | for c in iter {
| ---- `iter` moved due to this implicit call to `.into_iter()`
6 | let current: char = c;
7 | let next: char = *iter.peek().unwrap_or(&'∅');
| ^^^^^^^^^^^ value borrowed here after move
|
note: this function takes ownership of the receiver `self`, which moves `iter`
--> /home/james/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/iter/traits/collect.rs:267:18
|
267 | fn into_iter(self) -> Self::IntoIter;
Any idea what's going on here? I've tried various combinations of referencing and dereferencing but nothing I've tried seems to work.
The iterator is moved into the for loop. You cannot manually manipulate an iterator inside a for loop. However, the for loop can be replaced by while let:
while let Some(c) = iter.next() {
let current: char = c;
let next: char = *iter.peek().unwrap_or(&'∅');
}
Playground.
If you can work with slices, it will get much easier with windows():
let slice = ['1', '2', '3', '4', '5'];
let iter = slice.windows(2);
for arr in iter {
let current = arr[0];
let next = arr[1];
}
Playground

Dealing with clone

I'm trying to iterate over a VCF file and create vectors with the data to build a DataFrame.
However, the rust compilator is raising an error saying that the borrowed value does not live enough.
I'm cloning the value because, in that case, I'm borrowing the vcf record as immutable and as mutable at the same time.
I don't know how to proceed. Below there are the snippet of my code and the error.
use flate2::read::MultiGzDecoder;
use std::fs::File;
use std::io::BufReader;
mod vcf_reader;
use vcf::{VCFReader, U8Vec, VCFHeaderFilterAlt, VCFError, VCFRecord};
use vcf_reader::reader::VCFSamples;
use polars_core::prelude::*;
use std::time::Instant;
fn main() -> Result<()> {
let now = Instant::now();
let mut reader = VCFReader::new(BufReader::new(File::open(
"C:\\Users\\Desktop\\rust_lectures\\vcf_reader\\vcf_reader\\*.vcf"
)?)).unwrap();
// prepare VCFRecord object
let mut vcf_record = VCFRecord::new(reader.header());
// read one record
let mut chromosome = Vec::new();
let mut position = Vec::new();
let mut id = Vec::new();
let mut reference = Vec::new();
let mut alternative = Vec::new();
let result: bool = reader.next_record(&mut vcf_record).unwrap();
loop {
let row = vcf_record.clone();
if result == false {
let df = df!(
"Chromosome" => chromosome,
"Position" => position,
"Id" => id,
"Reference" => reference,
"Alternative" => alternative,
);
println!("{:?}", df);
let elapsed = now.elapsed();
println!("Elapsed: {:.2?}", elapsed);
return Ok(())
} else {
chromosome.push(String::from_utf8_lossy(&row.chromosome));
position.push(&row.position);
id.push(String::from_utf8_lossy(&row.id[0]));
reference.push(String::from_utf8_lossy(&row.reference));
alternative.push(String::from_utf8_lossy(&row.alternative[0]));
}
reader.next_record(&mut vcf_record).unwrap();
}
error[E0597]: `row.chromosome` does not live long enough
--> src\main.rs:44:53
|
44 | chromosome.push(String::from_utf8_lossy(&row.chromosome));
| ----------------------------------------^^^^^^^^^^^^^^^^^^^^--
| | |
| | borrowed value does not live long enough
| borrow later used here
...
50 | }
| - `row.chromosome` dropped here while still borrowed
I'm cloning the value because
The problem is that you're cloning the record but then you're storing references into your arrays. Since those are references to the cloned record, they only live until the end of the block.
So either:
move the attributes out of the clone (essentially explode it)
or rather than working with a copy of the record, copy individual fields out of the base vcf_record
Either way you're also misusing from_utf8_lossy: it always returns a reference-ish, because it avoids allocating if the input is valid utf8 (in that case it essentially just returns a reference to the original data).

Cannot assign to `x` because it is borrowed

Getting the below error when trying to push more elements to a vector. How to overcome this error
error[E0506]: cannot assign to `x` because it is borrowed
x = format!(r"\*START TIME*{:?}\S*\s+(?P<Value>[a-zA-Z0-9_\-\.]+)", ts);
| ^^ assignment to borrowed `x` occurs here
76 | core_regex_dict.push(&x);
| --------------- --- borrow of `x` occurs here
| |
| borrow later used here
Code:
let mut x = String::new();
for ts in test_list {
x = format!(r"\*START TIME*{:?}\S*\s+(?P<Value>[a-zA-Z0-9_\-\.]+)", ts);
core_regex_dict.push(&x);
}
It's hard to answer your question because you didn't give us enough information. In particular, we need to know how core_regex_dict is defined. I'm assuming that core_regex_dict has type Vec<&str>. You need to change that to Vec<String>:
let core_regex_dict = Vec::new(); // No need to specify the item type, it will be inferred.
// No need to declare `x` before the loop unless you need to use the
// last value afterward...
for ts in test_list {
let x = format!(r"\*START TIME*{:?}\S*\s+(?P<Value>[a-zA-Z0-9_\-\.]+)", ts);
core_regex_dict.push (x); // No `&` -> we push the String itself instead of a reference
}
Found a solution that involves leaking the memory of the String in https://stackoverflow.com/a/30527289/12323498
But, is there a better way to achieve this without leaking the memory?
fn string_to_static_str(s: String) -> &'static str {
Box::leak(s.into_boxed_str())
}
and the code look like this now
let mut s = String::new();
for ts in test_list {
s = format!(r"\*START TIME*{:?}\S*\s+(?P<Value>[a-zA-Z0-9_\-\.]+)", ts);
let s: &'static str = string_to_static_str(s);
core_regex_dict.push(s);
}

Why does a variable holding the result of Vec::get_mut not need to be mutable?

I have the following code:
fn main() {
let mut vec = Vec::new();
vec.push(String::from("Foo"));
let mut row = vec.get_mut(0).unwrap();
row.push('!');
println!("{}", vec[0])
}
It prints out "Foo!", but the compiler tells me:
warning: variable does not need to be mutable
--> src/main.rs:4:9
|
4 | let mut row = vec.get_mut(0).unwrap();
| ----^^^
| |
| help: remove this `mut`
Surprisingly, removing the mut works. This raises a few questions:
Why does this work?
Why doesn't this work when I use vec.get instead of vec.get_mut, regardless of whether I use let or let mut?
Why doesn't vec work in the same way, i.e. when I use let vec = Vec::new(), why can't I call vec.push()?
vec.get_mut(0) returns an Option<&mut String>, so when you unwrap that value you will have a mutable borrow of a String. Remember, that a let statement's left side is using pattern matching, so when your pattern is just a variable name you essentially say match whatever is on the right and call it name. Thus row matches against &mut String so it already is mutable.
Here's a much simpler and more straightforward example to illustrate the case (which you can try in the playground):
fn main() {
let mut x = 55i32;
dbg!(&x);
let y = &mut x; // <-- y's type is `&mut i32`
*y = 12;
dbg!(&x);
}

When an immutable reference to a mutable reference to a value outside the scope is returned, why is the mutable reference dropped when the scope ends?

fn main() {
// block1: fails
{
let mut m = 10;
let n = {
let b = &&mut m;
&**b // just returning b fails
};
println!("{:?}", n);
}
// block2: passes
{
let mut m = 10;
let n = {
let b = &&m;
&**b // just returning b fails here too
};
println!("{:?}", n);
}
}
block1 fails with the error:
error[E0597]: borrowed value does not live long enough
--> src/main.rs:7:22
|
7 | let b = &&mut m;
| ^^^^^^ temporary value does not live long enough
8 | &**b // just returning b fails
9 | };
| - temporary value dropped here while still borrowed
...
12 | }
| - temporary value needs to live until here
Am I correct in assuming that the inner immutable reference is extended beyond the block2 scope, whereas in block1, the inner mutable reference is always dropped even if there is an outer reference to it?
It is sufficient here to think of a mutable borrow as a non-Copy struct (S in the snippets below) which takes ownership of the referenced value. This model represents the exclusive nature of a mutable borrow.
Reasoning based on this model: In block2 n is a reference to the original m, while in block1 n would end up being a reference to a copy of m owned by the mutable borrow. In both blocks the inner reference is dropped at the end of the let-block, but only in block1 this causes a problem, because in block1 the target of the reference for n is still owned by the inner reference when this inner reference is dropped.
struct S { m: i32 }
let mut m = 10;
let n = {
let s = S { m };
let b = &s;
&(*b).m
}; // s is dropped
println!("{:?}", n);
In the snippet above s takes ownership of a copy of m. The reference n would point to that copy of n which is dropped when s is dropped - not allowed. If m was non-Copy, m would be moved into s, which would have the same implications.
In block2 the original m is borrowed directly without copying it. If you force a copy, you will get the same error as for block1:
let mut m = 10;
let n = {
let m2 = m;
let mut a = &m2;
let b = &a;
&**b
};
println!("{:?}", n);

Resources