Reference passed as parameter is not moved - rust

fn t(x: &mut u8) -> &mut u8 {
x
}
fn main() {
let mut x = 5u8;
let y = & mut x;
let z = t(y);
println!("{}", y);
}
Compiling this gives me this error:
main.rs:9:20: 9:21 error: cannot borrow `y` as immutable because `*y` is also borrowed as mutable
main.rs:9 println!("{}", y);
I would have thought y would have been moved during the call to t and then back to z, resulting in an error: use of moved value
Why do I get this error message instead?
Does Rust automatically create a new borrow instead of passing ownership when references are offered as function parameters?
What is the purpose of this behaviour?

You are returning a mutable reference to the parameter from your function. However, Rust doesn't know that the method hasn't kept a copy of that pointer didn't return a subsection of that pointer, were it a struct. This means that at any time, the value pointed to might be changed, which is a big no-no in Rust; if it were allowed, then you could easily cause memory errors.
Does Rust automatically create a new borrow
Yes, Rust "re-borrows" references.
A better example requires a smidge more complexity:
struct Thing { a: u8, b: u8 }
fn t(x: &mut Thing) -> &mut u8 {
&mut x.a
}
fn main() {
let mut x = Thing { a: 5, b: 6 };
let z = t(&mut x);
*z = 0;
// x.a = 0; // cannot assign to `x.a` because it is borrowed
}
Here, t returns a mutable pointer to a subset of the struct. This means that the entire struct is borrowed, and we cannot change it (except via z). Rust applies this logic to all functions, and doesn't try to recognize that your t function just returns the same pointer.

By compiling your program with rustc --pretty=expanded, we can see that the println! macro borrows its argument:
#![no_std]
#[macro_use]
extern crate "std" as std;
#[prelude_import]
use std::prelude::v1::*;
fn t(x: &mut u8) -> &mut u8 { x }
fn main() {
let mut x = 5u8;
let y = &mut x;
let z = t(y);
::std::io::stdio::println_args(::std::fmt::Arguments::new({
#[inline]
#[allow(dead_code)]
static __STATIC_FMTSTR:
&'static [&'static str]
=
&[""];
__STATIC_FMTSTR
},
&match (&y,) { // <----- y is borrowed here
(__arg0,)
=>
[::std::fmt::argument(::std::fmt::String::fmt,
__arg0)],
}));
}

Related

Implement mem::swap in rust without std lib

I am trying to write a mem::swap function without using any std lib functions. i am totally new to rust and still trying to make sense of how to use rust language.
below is my code
fn swap<T: std::fmt::Display>(x: &mut T, y: &mut T) {
unsafe {
// Give ourselves some scratch space to work with
let mut t: &mut T = y;
y = x;
x = t;
}
}
fn main() {
println!("Hello, world!");
let mut x = Box::new(5);
let mut y = Box::new(42);
let mut t = Box::new(0);
swap(&mut x, &mut y);
}
and i am facing below error
error: lifetime may not live long enough
--> src/main.rs:4:29
|
1 | fn swap<T: std::fmt::Display>(x: &mut T, y: &mut T) {
| - - let's call the lifetime of this reference `'2`
| |
| let's call the lifetime of this reference `'1`
...
4 | let mut t: &mut T = y;
| ^ assignment requires that `'2` must outlive `'1`
|
help: consider introducing a named lifetime parameter
|
1 | fn swap<'a, T: std::fmt::Display>(x: &'a mut T, y: &'a mut T) {
| +++ ++ ++
what does 'lifetime may not live long enough' mean ?
is there a simple way to write mem::swap code in rust ?
You need to Copy the data. The reference you're using is useless for this purpose. You need to actually alter what both x and y reference.
For example:
fn swap<T>(a: &mut T, b: &mut T) where T : Copy {
(*a,*b) = (*b, *a)
}
fn main() {
let mut a = 1;
let mut b = 2;
swap(&mut a,&mut b);
println!("a={}, b={}", a, b);
}
If you set up the conditions here, it's really a one-liner, Rust will figure out the "temporary" stuff for you. In fact, having a function to do this is actually kind of overkill, since you can just do that single line anywhere in your code as you would normally.
Maybe you want to optimize this around boxed values, taking Box<T> as an argument instead, in which case you could swap references within the box instead of copying, but that's a specialization.
How about using core::ptr::swap to swap raw pointers *mut T.
use core::ptr::swap;
fn custom_swap<T>(x: &mut T, y: &mut T) {
unsafe {
(x as *mut T).swap(y as *mut T);
}
}
fn main() {
println!("Hello, world!");
let mut x = Box::new(5);
let mut y = Box::new(42);
println!("x={}, y={}", x, y);
custom_swap(&mut x, &mut y);
println!("x={}, y={}", x, y);
}
output
Hello, world!
x=5, y=42
x=42, y=5

Prevent cannot borrow `*self` as immutable because it is also borrowed as mutable when accessing disjoint fields in struct?

Prior question that this is not a duplicate of:
cannot borrow `*self` as mutable because it is also borrowed as immutable
This question is not relevant b/c the answer ended up being "the Rust compiler has a bug", which I'm pretty sure is not the case here.
I have the following structs:
struct Foo {
data: Vec<Bar>,
a: usize,
}
struct Bar {
b: usize
}
Inside impl Foo, I have the following methods:
fn example(&mut self, c: usize) {
let baz = &mut self.data[c];
let z = self.calc(c);
baz.b = 42 + z;
}
fn calc(&self, x: usize) -> usize {
self.a * x
}
Of course, the Rust compiler throws an error saying roughly "a mutable borrow occurs when you create baz, then you do an immutable borrow when you call self.calc and lastly you later use the mutable borrow when you assign to baz.a.
However, I'm accessing disjoint fields on the struct because calc never reads from data that is being written to through baz.
Is there a way to inform the Rust compiler of this?
The problem is the signature of Foo::calc, which takes &self as the receiver. This guarantees to calc that there are no mutable references to all of self, including any of its fields; that is, all of Foo is guaranteed to be immutable from the body of calc's point of view. This is not possible with the code as it is, because self.calc(c) requires to immutably borrow self (all of self) while a mutable borrow is still active.
The fact that calc never reads from data that is being written to baz is irrelevant. In Rust, all there is to know about a function or method is exposed in the signature; the compiler never looks "into" a function to figure out if it's a special case or not.
You can avoid the problem by not requiring calc to take &self as a receiver. For instance, by borrowing individual fields before the call (Self::calc(&self.a, c)) or, as in the example below, by not borrowing self at all:
impl Foo {
fn example(&mut self, c: usize) {
let baz = &mut self.data[c];
// This avoids borrowing `self` in its entirety...
let z = Self::calc(self.a, c);
baz.b = 42 + z;
}
fn calc(a: usize, x: usize) -> usize {
a * x
}
}
I ended up doing:
fn example(&mut self, c: usize) {
let baz = &self.data[c];
// some stuff that requires reading `baz`
let z = self.calc(c);
let baz = &mut self.data[c];
baz.b = 42 + z;
}
fn calc(&self, x: usize) -> usize {
self.a * x
}

Assignment of references in Rust

The following code doesn't compile, because x is used after move (since x has type &mut u8, which does not implement the Copy trait)
fn main() {
let mut a: u8 = 1;
let x: &mut u8 = &mut a;
let y = x;
x;
}
And as I understand y implicitly has type &mut u8
But if I specify the type of y explicitly it compiles. The following code compiles
fn main() {
let mut a: u8 = 1;
let x: &mut u8 = &mut a;
let y: &mut u8 = x;
x;
}
By the way if I change let y: &mut u8 = x; to let y: &u8 = x; it also compiles.
It seems to me nothing has changed, y is &mut u8 in the first example and it is &mut u8 in the second but the former doesn't compile and the latter does compile.
Why? What's the difference?
&mut u8 is not a complete type. All reference types must have a lifetime parameter on them. When you elide it, the Rust compiler must infer it, and it will pick the shortest lifetime possible. In your first example, the first step of desugaring is (using a fake syntax from the Rustonomicon):
fn main() {
let mut a: u8 = 1;
'a: {
let x: &'a mut u8 = &'a mut a; // the lifetime of x must last until it's use at the end
let y = x;
x;
}
}
This is still not completely explicit, since the type of y is still not known. What is it? Well, since it's being assigned from x, which is a &'a mut u8, it should also be a &'a mut u8. Note that this is not following the "shortest lifetime possible" rule of lifetime elision. You didn't elide a lifetime, you elided the whole type, which is reconstructed by type inference.
fn main() {
let mut a: u8 = 1;
'a: {
let x: &'a mut u8 = &'a mut a; // the lifetime of x must last until its use at the end
let y: &'a mut u8 = x;
x;
}
}
Well, that's no good. Since y has the same lifetime as x, its creation involves moving the reference in x and making x invalid. The program is thus rejected for trying to use x.
Adding the signature to y essentially gives the compiler a new place where it can infer lifetimes. Before, normal type inference made y have the same type as x, which meant it lasted as long as x and made x unusable. Now, y doesn't need to have the same type as x; the lifetime of the borrow can be different. In particular, it is made shorter.
fn main() {
let mut a: u8 = 1;
'a: {
let x: &'a mut u8 = &'a mut a; // the lifetime of x must last until it's use at the end
'b: {
let y: &'b mut u8 = x; // y and x can now have different lifetimes, *x is reborrowed here
}
x; // x not moved from, still valid
}
}
Now, instead of moving the reference x into y and making it invalid, the value *x is temporarily "reborrowed" to make y, as by let y: &'b mut u8 = &'b mut *x.
The other possible fix is to explicitly say "borrow *x again with a different lifetime":
fn main() {
let mut a: u8 = 1;
let x: &mut u8 = &mut a;
let y = &mut *x;
x;
}
The principle is the same as before: saying & more often gives the compiler more places where it can massage the lifetimes in the program to make everything work.

Can't borrow mutably within two different closures in the same scope

My goal is to make a function (specifically, floodfill) that works independent of the underlying data structure. I tried to do this by passing in two closures: one for querying, that borrows some data immutably, and another for mutating, that borrows the same data mutably.
Example (tested on the Rust Playground):
#![feature(nll)]
fn foo<F, G>(n: i32, closure: &F, mut_closure: &mut G)
where
F: Fn(i32) -> bool,
G: FnMut(i32) -> (),
{
if closure(n) {
mut_closure(n);
}
}
fn main() {
let mut data = 0;
let closure = |n| data == n;
let mut mut_closure = |n| {
data += n;
};
foo(0, &closure, &mut mut_closure);
}
Error: (Debug, Nightly)
error[E0502]: cannot borrow `data` as mutable because it is also borrowed as immutable
--> src/main.rs:16:27
|
15 | let closure = |n| data == n;
| --- ---- previous borrow occurs due to use of `data` in closure
| |
| immutable borrow occurs here
16 | let mut mut_closure = |n| {
| ^^^ mutable borrow occurs here
17 | data += n;
| ---- borrow occurs due to use of `data` in closure
18 | };
19 | foo(0, &closure, &mut mut_closure);
| -------- borrow later used here
I did come up with a solution, but it is very ugly. It works if I combine the closures into one and specify which behavior I want with a parameter:
// #![feature(nll)] not required for this solution
fn foo<F>(n: i32, closure: &mut F)
where
F: FnMut(i32, bool) -> Option<bool>,
{
if closure(n, false).unwrap() {
closure(n, true);
}
}
fn main() {
let mut data = 0;
let mut closure = |n, mutate| {
if mutate {
data += n;
None
} else {
Some(data == n)
}
};
foo(0, &mut closure);
}
Is there any way I can appease the borrow checker without this weird way of combining closures?
The problem is rooted in the fact that there's information that you know that the compiler doesn't.
As mentioned in the comments, you cannot mutate a value while there is a immutable reference to it — otherwise it wouldn't be immutable! It happens that your function needs to access the data immutably once and then mutably, but the compiler doesn't know that from the signature of the function. All it can tell is that the function can call the closures in any order and any number of times, which would include using the immutable data after it's been mutated.
I'm guessing that your original code indeed does that — it probably loops and accesses the "immutable" data after mutating it.
Compile-time borrow checking
One solution is to stop capturing the data in the closure. Instead, "promote" the data to an argument of the function and the closures:
fn foo<T, F, G>(n: i32, data: &mut T, closure: F, mut mut_closure: G)
where
F: Fn(&mut T, i32) -> bool,
G: FnMut(&mut T, i32),
{
if closure(data, n) {
mut_closure(data, n);
}
}
fn main() {
let mut data = 0;
foo(
0,
&mut data,
|data, n| *data == n,
|data, n| *data += n,
);
}
However, I believe that two inter-related closures like that will lead to poor maintainability. Instead, give a name to the concept and make a trait:
trait FillTarget {
fn test(&self, _: i32) -> bool;
fn do_it(&mut self, _: i32);
}
fn foo<F>(n: i32, mut target: F)
where
F: FillTarget,
{
if target.test(n) {
target.do_it(n);
}
}
struct Simple(i32);
impl FillTarget for Simple {
fn test(&self, n: i32) -> bool {
self.0 == n
}
fn do_it(&mut self, n: i32) {
self.0 += n
}
}
fn main() {
let data = Simple(0);
foo(0, data);
}
Run-time borrow checking
Because your code has a temporal need for the mutability (you only need it either mutable or immutable at a given time), you could also switch from compile-time borrow checking to run-time borrow checking. As mentioned in the comments, tools like Cell, RefCell, and Mutex can be used for this:
use std::cell::Cell;
fn main() {
let data = Cell::new(0);
foo(
0,
|n| data.get() == n,
|n| data.set(data.get() + n),
);
}
See also:
When I can use either Cell or RefCell, which should I choose?
Situations where Cell or RefCell is the best choice
Need holistic explanation about Rust's cell and reference counted types
Unsafe programmer-brain-time borrow checking
RefCell and Mutex have a (small) amount of runtime overhead. If you've profiled and determined that to be a bottleneck, you can use unsafe code. The usual unsafe caveats apply: it's now up to you, the fallible programmer, to ensure your code doesn't perform any undefined behavior. This means you have to know what is and is not undefined behavior!
use std::cell::UnsafeCell;
fn main() {
let data = UnsafeCell::new(0);
foo(
0,
|n| unsafe { *data.get() == n },
|n| unsafe { *data.get() += n },
);
}
I, another fallible programmer, believe this code to be safe because there will never be temporal mutable aliasing of data. However, that requires knowledge of what foo does. If it called one closure at the same time as the other, this would most likely become undefined behavior.
Additional comments
There's no reason to take references to your generic closure types for the closures
There's no reason to use -> () on the closure type, you can just omit it.

How can I borrow from a HashMap to read and write at the same time?

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.

Resources