This question already has answers here:
Why can't I reuse a &mut reference after passing it to a function that accepts a generic type?
(1 answer)
Why does creating a mutable reference to a dereferenced mutable reference work?
(3 answers)
Do all primitive types implement the Copy trait?
(1 answer)
Closed 1 year ago.
Consider this code:
struct A;
trait Test {
fn test(self);
}
impl Test for &mut A {
fn test(self) {
println!("&mut Test called");
}
}
fn test(a: &mut A) {
a.test();
}
fn test2(a: impl Test) {
a.test();
}
fn main() {
let mut a = A;
let a_mut_ref = &mut a;
test(a_mut_ref); // works fine
test(a_mut_ref); // works fine
test2(a_mut_ref); // `a_mut_ref` moved here? Why?
test2(a_mut_ref); // compile error `use of moved value` here
}
According to Rust's docs, mutable references do not implement Copy.
Why does calling test twice work fine?
Why does not it work with test2 the same way?
How can I change test2 to keep both impl-like boundary and get successful compilation?
Related
This question already has answers here:
What are Rust's exact auto-dereferencing rules?
(4 answers)
Closed 18 days ago.
According to my understanding, next needs a &mut Test, but create_test() returns a Test.
Why can this be compiled?
My guess is that . will implicitly convert Test to &mut Test, I am not sure. Can somebody explain more about this?
pub struct Test {
t: u64,
}
fn create_test() -> Test {
Test {
t: 1
}
}
impl Test {
pub fn next(&mut self) {
self.t = 10;
}
}
fn main() {
let mut t = Test { t: 20 };
t.next();
create_test().next(); // here
}
This is explained in the Method-call expressions section of the book.
When looking up a method call, the receiver may be automatically dereferenced or borrowed in order to call a method.
This is exactly what is happening here. The rust compiler is automatically borrowing value returned create_test.
This question already has answers here:
Why is the mutable reference not moved here?
(4 answers)
Do mutable references have move semantics?
(1 answer)
Closed 1 year ago.
In the below code I was expecting the compiler to complain about use of moved value: xref on hello function's second call since mutable references do not implement Copy. The compiler doesn't raise any such error. What am I missing here?
fn main() {
let mut x: String = "Developer".to_string();
let x_ref: &mut String = &mut x;
hello(x_ref);
hello(x_ref);
}
fn hello(a: &mut String) {
println!("Hello {}", a);
}
Your example uses the mutable references after each other, which allows the compiler to perform an implicit reborrow. It basically turns this code into this:
hello(&mut *x_ref);
hello(&mut *x_ref);
Now you have two separate mutable borrows each only for the lifetime of the function call, thus they do not conflict with each other.
You see an error if you try to use it two times simultaneously.
fn main() {
let mut x: String = "Developer".to_string();
let x_ref: &mut String = &mut x;
hello(x_ref, x_ref);
}
fn hello(a: &mut String, b: &mut String) {
println!("Hello {} and {}", a, b);
}
This question already has answers here:
How do I return a reference to something inside a RefCell without breaking encapsulation?
(3 answers)
How do I borrow a RefCell<HashMap>, find a key, and return a reference to the result? [duplicate]
(1 answer)
Closed 2 years ago.
How can I return a reference to something from inside a shared pointer (in this case Rc<RefCell<_>>)? In the example below, I show how it can be done with just a regular mutable reference to self, but if it becomes a shared pointer instead, the compiler gets angry that the return type has a missing lifetime specifier.
error[E0106]: missing lifetime specifier
--> src/main.rs:19:60
|
19 | fn add_to_shared(me: Rc<RefCell<Thing>>, item: i32) -> &i32 {
| ^ expected named lifetime parameter
|
= help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
help: consider using the `'static` lifetime
|
19 | fn add_to_shared(me: Rc<RefCell<Thing>>, item: i32) -> &'static i32 {
| ^^^^^^^^
use std::cell::RefCell;
use std::rc::Rc;
struct Thing {
items: Vec<i32>,
}
impl Thing {
fn new() -> Self {
Thing { items: Vec::new() }
}
fn add_to_self(&mut self, item: i32) -> &i32 {
self.items.push(item);
self.items.last().unwrap()
}
// does not compile
fn add_to_shared(me: Rc<RefCell<Thing>>, item: i32) -> &i32 {
me.borrow().items.push(item);
me.borrow().items.last().unwrap()
}
}
fn main() {
let mut thing = Thing::new();
println!("{}", thing.add_to_self(10));
let mut rc = Rc::new(RefCell::new(Thing::new()));
println!("{}", rc.add_to_shared(20));
}
Why do I want to do this? I have a program that builds a tree-like structure with multiple ownership. One of the associated methods takes two nodes of the tree (each shared pointers) and bundles them together into another part of the tree. Each method returns a reference to the newly created node so that it can be conveniently logged out (see the example).
I was thinking I'd need to use lifetime annotations to get this to work, but I have not been able to find out how do apply this concept to the interior of a Rc<RefCell<_>> type.
I think the problem here is that Rust knows how long self lives, but is not able to figure out how long Rc<RefCell<_>> exists. Do you need to return i32 references? If you would return just i32, the value would be copied and you would not have a reference into a struct that might not exists long enough.
This question already has answers here:
Is it possible to create a wrapper around an &mut that acts like an &mut
(1 answer)
Why is the mutable reference not moved here?
(4 answers)
Closed 2 years ago.
I've been adapting some old code I wrote, one of them had the following (simplified):
pub fn a(x: &mut i32) {
for i in 0..10 {
b(x);
}
}
pub fn b(_x: &mut i32) {
}
which worked fine, even though &mut i32 isn't Copy.
I wanted to restrict what methods could be called on the underlying type, (as instead of &mut i32 I had something along the lines of &mut Vec<...>), so I created a wrapper type over the mutable reference:
#[derive(Debug)]
pub struct I32RefMut<'a>(&'a mut i32);
And I attempted to rewrite a and b using this wrapper as follows:
pub fn a2(x: I32RefMut) {
for _i in 0..10 {
b2(x);
}
}
pub fn b2(_x: I32RefMut) {
}
This gives the following error
17 | pub fn a2(x: I32RefMut) {
| - move occurs because `x` has type `I32RefMut<'_>`, which does not implement the `Copy` trait
18 | for _i in 0..10 {
19 | b2(x);
| ^ value moved here, in previous iteration of loop
Playground link
Which is understandable, as x gets moved into b2 on the first iteration of the loop.
Unfortunately I cannot implement Clone nor Copy, as there may only be 1 mutable reference to the object at a time.
My question is how does &mut i32 work around this and how can I implement this workaround (or similar) on my type I32RefMut.
If possible I'd like to avoid unsafe code as much as possible, such as using #[repr(transparent)] struct I32Wrapper(i32) and then transmuting &mut i32 to &mut I32Wrapper, unless a safe wrapper of this type of operation exists already.
EDIT:
Found a "hack" solution, but I'm not very happy about how it looks, so I'll leave the question open. If no other solutions are found, I'll post it as an answer.
If the call to b2 is changed to b2( I32RefMut(x.0) ), then it successfully compiles. This however, cannot be generalised to a function as such:
impl<'a> I32RefMut<'a> {
pub fn my_clone<'b: 'a>(&'b mut self) -> I32RefMut<'b> {
I32RefMut( self.0 )
}
}
As when we try to call it the compiler tells us we can't borrow x mutably twice.
As this wrapper type is supposed to be defined in a library, I cannot expose it's internal reference, as the whole point of the wrapper was to restrain what the user can call on the reference.
The thing is that you are taking ownership of your new type instance when calling b. Just take a reference to your type instead to get access to the underlaying type:
pub fn a2(x: &I32RefMut) {
for _i in 0..10 {
b2(x);
}
}
pub fn b2(_x: &I32RefMut) {
}
Playground
Actually if you want to mutate it you need to play around a bit with them:
pub fn a2(mut x: I32RefMut) {
for _i in 0..10 {
b2(&mut x);
}
}
pub fn b2(_x: &mut I32RefMut) {
*(_x.0) += 1
}
Playground
This question already has answers here:
Mutably borrow one struct field while borrowing another in a closure
(2 answers)
Closed 5 years ago.
This snippet
use std::collections::HashMap;
struct Foo {
local_ids: HashMap<i32, i32>,
last_id: i32,
}
impl Foo {
fn foo(&mut self, external_id: i32) {
let id = self.local_ids
.entry(external_id)
.or_insert_with(||{self.last_id += 1; self.last_id});
}
}
Doesn't work because we can't borrow self twice
error: closure requires unique access to `self` but `self.local_ids` is already borrowed [E0500]
Is this possible to fix without a second key lookup?
This is very similar to Rust: HashMap borrow issue when trying to implement find or insert, but the API has changed substantially.
The find_with_or_insert_with answer from above doesn't appear to map to the current api.
The problem is that the closure captures self, whereas it only needs to capture a mutable reference to the last_id field.
Rust allows us to take independent mutable borrows on distinct fields, so we can use that to our advantage and pass a mutable reference to the last_id field to the closure.
use std::collections::HashMap;
struct Foo {
local_ids: HashMap<i32, i32>,
last_id: i32,
}
impl Foo {
fn foo(&mut self, external_id: i32) {
let last_id = &mut self.last_id;
let id = self.local_ids
.entry(external_id)
.or_insert_with(|| { *last_id += 1; *last_id });
}
}
When we use the expression self.last_id in the closure, the closure captures self directly, but Rust doesn't realize that the borrows are independent, so we need to be more explicit.