Rust mutable variable and String [duplicate] - rust

This question already has answers here:
When does Rust drop the value in case of reassignment? [duplicate]
(1 answer)
Does Rust free up the memory of overwritten variables?
(3 answers)
Closed 2 months ago.
I have the following piece of code
{
let mut a = String::from("Foo");
a = String::from("Bar");
}
I'm wondering when will the first String be freed is it when I assign a to a different String ? or is it when the scope ends ?

You can easily test this:
struct B(&'static str);
impl Drop for B {
fn drop(&mut self) {
println!("{} B dropped", self.0)
}
}
fn main() {
{
let mut b = B("first");
println!("{} B created", b.0);
b = B("second");
println!("{} B reasigned", b.0);
}
}
This outputs:
first B created
first B dropped
second B reasigned
second B dropped
So the first instance of B is dropped when the variable is re-assigned. The second one is dopped at the end of the function.
Playground link to try it yourself

Related

what happens to a rust mutable value after each assignment [duplicate]

This question already has answers here:
Does Rust free up the memory of overwritten variables?
(3 answers)
When does Rust drop the value in case of reassignment? [duplicate]
(1 answer)
Closed 15 days ago.
Here are two examples of dynamic mutable value.
pub fn main() {
let mut x = String::from("Hello");
println!("{}", x);
x = format!("{x}, world!");
println!("{}", x);
}
So as you can see, we have a mutable variable x. x gets borrowed by format! & turns to a new value that is then assigned back to x.
pub fn main() {
let mut x = String::from("Hello, world!");
println!("{}", x);
x = String::from("Lorem, ipsum!");
println!("{}", x);
}
My real problem is this code, where the value assigned to x has no connection with it's initial value. Variables can only take owner-ship over a single value, so how does Rust keep track of "Hello, world!" & "Lorem, ipsum!"? Exactly what happens to mutable values after assignments?
My guess is that it checks if the value getting assigned to depends on the first one, if yes, it won't drop it.

Why doesn't a trait object move when it calls enumerate()? [duplicate]

This question already has an answer here:
Do mutable references have move semantics?
(1 answer)
Closed 1 year ago.
Let me give the code first
fn dump(iter: &mut dyn Iterator<Item=String>) {
for (i, v) in iter.enumerate() {
println!("{} {}", i, v);
}
for v in iter {
println!("{}", v);
}
}
#[test]
fn test_trait() {
let v = vec!["a".to_string(), "b".to_string(), "c".to_string()];
let mut iter = v.into_iter();
dump(&mut iter);
}
Here is the output when I run this test
running 1 test
0 a
1 b
2 c
test test_trait ... ok
Why the iter not moved when calling enumerate?
The enumerate is accepting self as its first argument, so I think it should move the iter,
but it doesn't! The second for-loop can still run, without any compilation error.
In this case, Self is actually &mut (dyn Iterator<Item = String>) making the enumerate call return Enumerate<&mut (dyn Iterator<Item = String>)>. I am not that familiar how Rust deals with this kind of dynamic trait objects but my guess is that what gets dropped at the end of enumeration is actually the reference.
By the way - if you are using VSCode and the Rust analyzer extension, you can turn on the "Inlay Hints: Type Hints" option to see the types of things.
There is a similar option for the Intellij Idea IDE that I can not remember off the top of my head. That way I was able to see the type by making a variable of the enumeration and this is what it showed:
let a: Enumerate<&mut (dyn Iterator<Item = String>)>

How do I write a function that does not take ownership (or does not consume) an iterator? [duplicate]

This question already has answers here:
Why can't I use `&Iterator<Item = &String>` as an iterator?
(3 answers)
How do I create a function that accepts an iterator of i32s as either values or references and sums them?
(1 answer)
How to write a Rust function that takes an iterator?
(3 answers)
Closed 2 years ago.
I have a function that takes a &Vector<T>. I want to change it to take an iterator in order to run it on different container/collection/slice types.
It produces an error because the function is called twice.
What I Have So Far
fn operate_on_iterator<'a>(iterator: &impl IntoIterator<Item = i32>) -> i32 {
// This is an example. Please don't tell me to use `.sum`.
let mut sum = 0;
for val in iterator.into_iter() {
sum += val;
}
sum
}
fn caller() -> i32 {
let v = vec![1, 2, 3, 4];
let s1 = operate_on_iterator(&v);
let s2 = operate_on_iterator(&v);
s1 + s2
}
playground
The Error I Get
error[E0507]: cannot move out of `*iterator` which is behind a shared reference
--> src/lib.rs:13:16
|
13 | for val in iterator.into_iter() {
| ^^^^^^^^ move occurs because `*iterator` has type `impl IntoIterator<Item = i32>`, which does not implement the `Copy` trait
Restrictions and notes
I do not want to use dyn because I prefer the slightly larger code size over the performance impact of pointer dereferencing. (Although I will use it for now and will benchmark it once I have both traits and trait objects implemented, i.e. after I have an answer to this question.) Also using dyn also didn't work so far for me.
I have used this answer as a basis. How to write a Rust function that takes an iterator?
My Item implements Clone, Binding, and Drop.
I also tried to implement it using Iterator instead of IntoIterator. Also no luck.
Shepmaster linked to the answer.
For completeness, this is the necessary change:
&impl IntoIterator<Item = i32> -->
impl IntoIterator<Item = &'a i32>
Resulting in this code:
fn operate_on_iterator<'a>(iterator: impl IntoIterator<Item = &'a i32>) -> i32 {
// This is an example. Please don't tell me to use `.sum`.
let mut sum = 0;
for val in iterator.into_iter() {
sum += val;
}
sum
}

Is there a clean way in Rust to mutate a `&mut` by replacing its value? [duplicate]

This question already has answers here:
Temporarily move out of borrowed content
(3 answers)
How do you replace the value of a mutable variable by taking ownership of it?
(2 answers)
How can I swap in a new value for a field in a mutable reference to a structure?
(2 answers)
Closed 3 years ago.
Is there a clean way to implement a safe function g that mutates a mutable reference by applying f on its value without having to implement Clone or Default (or any other special trait) for T? If not, why is or should this not be possible?
Imagine a type T and a function f:
fn f(v: T) -> T;
For example:
fn f(mut v: u32) -> u32 {
v += 1;
v
}
The following code is invalid because p cannot be dereferenced:
fn g(p: &mut T) {
*p = f(*p)
}
I searched and tried many things, but I didn't come up with a safe solution.
For people who are interested for the cases where Clone and Default are allowed:
By implementing Clone you could do:
fn g(p: &mut T) {
*p = f(p.clone())
}
By implementing Default you could do:
fn g(p: &mut T) {
let val = core::mem::take(p);
core::mem::replace(p, f(val));
}

Struct str attribute must be reference? [duplicate]

This question already has answers here:
How to solve "returns a value referencing data owned by the current function" error in Rust? [duplicate]
(1 answer)
Return local String as a slice (&str)
(7 answers)
Why can't I return an &str value generated from a String?
(1 answer)
Is there any way to return a reference to a variable created in a function?
(5 answers)
Closed 3 years ago.
For the following code:
fn get_lines() -> String {
String::from("Hello\nWorld")
}
fn get_first_line(s: &String) -> &str {
s.lines().next().unwrap()
}
struct World<'a> {
a_str: &'a str,
}
fn work<'a>() -> World<'a> {
let s1 = get_lines();
let s2 = get_first_line(&s1);
World { a_str: s2 }
}
fn main() {
let w = work();
}
I got the following error:
error[E0515]: cannot return value referencing local variable `s1`
--> src/main.rs:17:5
|
15 | let s2 = get_first_line(&s1);
| --- `s1` is borrowed here
16 |
17 | World { a_str: s2 }
| ^^^^^^^^^^^^^^^^^^^ returns a value referencing data owned by the current function
How to build a struct instance using s2? Is it a conceptual error of the World struct?
World refers to a str slice which must be owned by something else. Your function work allocates a new String (through get_lines), and makes a reference into it (through get_first_line). When it returns, the String goes out of scope and will be dropped, so you cannot keep a reference to it, since the thing it refers to is no longer there.
If you want a World object that does not depend on a String owned by something else, it will need to own the data itself: Contain a String instead of a &'a str.
See also 'dangling references' in the Rust Book.

Resources