How to use data generated from builder pattern - rust

I'm new to Rust and this is basically the first Rust code I'm trying to write. Below is a simplified version of the problematic code I'm working on, but the errors are exactly the same.
struct A {
pub value : i32
}
impl A {
pub fn new() -> Self {
A {value : 0}
}
}
struct B {
vec_a : Vec<A>
}
impl B {
pub fn new() -> Self {
B {
vec_a : Vec::new()
}
}
pub fn create_A(&mut self) -> &mut A {
let a = A::new();
self.vec_a.push(a);
let last_index = self.vec_a.len() - 1;
&mut self.vec_a[last_index]
}
}
fn main() {
let mut b = B::new();
let a1 : &mut A = b.create_A();
let a2 : &mut A = b.create_A();
println!("{}, {}", a1.value, a2.value);
}
The code gives below compilation error:
error[E0499]: cannot borrow `b` as mutable more than once at a time
--> src/main.rs:32:23
|
31 | let a1 : &mut A = b.create_A();
| ------------ first mutable borrow occurs here
32 | let a2 : &mut A = b.create_A();
| ^^^^^^^^^^^^ second mutable borrow occurs here
33 |
34 | println!("{}, {}", a1.value, a2.value);
| -------- first borrow later used here
It seems to me that the compiler is telling me that the using of a1 is not safe as it is generated from b, and yet there is another mutable borrow of b after a1, that may change b, so that the data in a1 is invalid now. Am I understanding this error correctly? If so, how do I tell the compiler a1 and a2 are completely different part of b and using a1 later on is fine?
Code in Rust Playground

Yes your understanding is correct. a1 is borrowed from b, and while a1 exists, you cannot modify b.
If so, how do I tell the compiler a1 and a2 are completely different part of b and using a1 later on is fine?
That's wrong, and the fact that you assume it is possible shows how valuable the borrow checker is. Even in C++, your code would be undefined behaviour.
Adding an element to a vector could cause a memory reallocation, invalidating all references to elements in that vector. It's the same in C++.
Therefore the compiler is right: You cannot do this. self.vec_a.push() will potentially invalidate your a1 reference.
Even if a reallocation would not happen, your code would still be unsound.
Nothing in b keeps track of the references to the vector. Therefore if you could access b while a1 (a &mut reference into b) exists, you could get another reference &b.vec_a[0]. Then you would have a &mut and a & reference to the same A object at the same time, which is forbidden/unsound.
What are you trying to accomplish? I'm sure there is a different programming pattern that is more suited for Rust. The one you are using right now is simply not compatible with Rust.

Related

Mutably borrowing fields of struct results in an apparent contradiction in compiler error message

I'm having some trouble understanding the compiler error message for this code:
struct A {
b: B,
c: C,
}
struct B {
f: u32,
}
struct C {
f: u32,
}
fn foo(b: &mut B) -> &u32 { &b.f }
fn bar(c: &mut C) -> &u32 { &c.f }
fn quux(z: &mut A) -> u32 { z.b.f }
fn baz(a: &mut A) {
let x = foo(&mut a.b);
let y = bar(&mut a.c);
let z = quux(a); // equivalent to: quux(&mut *a)
println!("{} {}", x, y);
}
error[E0499]: cannot borrow `*a` as mutable more than once at a time
--> src/main.rs:22:18
|
20 | let x = foo(&mut a.b);
| -------- first mutable borrow occurs here
21 | let y = bar(&mut a.c);
22 | let z = quux(a);
| ^ second mutable borrow occurs here
23 | println!("{} {}", x, y);
| - first borrow later used here
For more information about this error, try `rustc --explain E0499`.
error: could not compile `playground` due to previous error
If line 20 is mutably borrowing *a (as the compilation error asserts), then line 21 must also mutably borrow *a (How couldn't it? It's nearly identical to line 20 -- only difference is which field is borrowed), so by my reasoning the code should still fail to compile after deleting line 22; however, the code actually compiles just fine if I delete line 22. The fact that this would then compile seems to contradict the compiler's claim that &mut a.b results in a mutable borrow of *a.
x and y are immutable borrows, so if anything I would expect a compilation error regarding the overlapping scopes of the immutable x/y and the mutable borrow of *a in line 22 (otherwise quux could conceivably mutate a while we're borrowing its fields).
What knowledge am I likely missing that makes this error message confusing to me? If you're not surprised by this message, could you break down how you reason about this?
Some more thinking before I submitted this question:
I suppose the immutable references returned from foo and bar somehow extend the original mutable borrows of a.b and a.c (why that would be necessary, I don't know). If that's the case, maybe the way to see this is that &mut a.b and &mut a.c in turn extend the mutable borrow of *a. The error message says the first mutable borrow of *a occurs on line 20, but maybe the way to see this is:
The true first borrow of *a is when when the caller gives us the &mut A.
While the compiler suggests there's a mutable borrow of *a on line 20, this isn't exactly the case: the mut &a.b expression borrows (*a).b, but merely extends the existing borrow given to us (as opposed to being a new mutable borrow of *a).
The last point, but with respect to mut &a.c.
Insert the aforementioned reasoning of "extending borrows" wrt *a.
The call to quux then mutably borrows the *a a second time.
So maybe what the compilation error calls the initial borrow of *a is actually reporting the location of the expression responsible for extending the original *a borrow?
Line 20 does not conflict with 21 since they borrow different fields within a and therefore cause no collision.
The issue is that foo and bar return references that inherit the lifetime of the mutable reference. Even though they return immutable references, their lifetimes rely on the lifetime of the mutable borrow. So by requiring they live for a period of time, by extension the mutable borrow must do so as well. The compiler always takes the function signature on face value so it can not downgrade the initial mutable reference. If it did not, it could lead to issues if the function was modified later or if it contained unsafe code that relied on consuming a mutable reference for safety.
Here is a counter example where all of the function signatures remain the same. Since the compiler can not make assumptions on how quux and foo will use their values quux may make the references returned by foo or bar invalid.
struct A {
b: B,
c: C,
}
struct B {
f: Option<u32>,
}
struct C {
f: u32,
}
fn foo(b: &mut B) -> &u32 {
b.f.as_ref().unwrap()
}
fn bar(c: &mut C) -> &u32 { &c.f }
fn quux(z: &mut A) -> u32 {
z.b.f = None;
z.c.f
}
fn baz(a: &mut A) {
let x = foo(&mut a.b);
let y = bar(&mut a.c);
let z = quux(a);
println!("{} {}", x, y);
}
There are two issues here. First: why does let x = foo(&mut a.b); prevent you from doing let z = quux(a);, and second why does let x = foo(&mut a.b); not prevent you from doing let y = bar(&mut a.c);?
Why does let x = foo(&mut a.b); prevent you from doing let z = quux(a);?
This is due to the lifetime elision rules. You declared foo as:
fn foo(b: &mut B) -> &u32
Since you use references there must be a lifetime, but since you didn't specify one yourself the compiler assumes that all references have the same lifetime. In other words, the compiler rewrites your code as:
fn foo<'a>(b: &'a mut B) -> &'a u32
Which means that the returned value has the same lifetime as the mutable borrow, so the mutable borrow lasts until the println where you use the return value x, which prevents other borrows of a.b or a as a whole.
But then why does let x = foo(&mut a.b); not prevent you from doing let y = bar(&mut a.c);?
That's because the compiler is smart enough to realize that a.b and a.c are disjoint parts of a, which can be borrowed without conflict (in the same way that you can borrow different local variables simultaneously).

Is this the idiomatic way to make self-referential structures?

I am interested in knowing the idiomatic/canonical way of making self-referential structures in Rust. The related question Why can't I store a value and a reference to that value in the same struct explains the problem, but try as I might, I couldn't figure out the answer in the existing question (although there were some useful hints).
I have come up with a solution, but I am unsure of how safe it is, or if it is the idiomatic way to solve this problem; if it isn't, I would very much like to know what the usual solution is.
I have an existing structure in my program that holds a reference to a sequence. Sequences hold information about chromosomes so they can be rather long, and copying them isn't a viable idea.
// My real Foo is more complicated than this and is an existing
// type I'd rather not have to rewrite if I can avoid it...
struct Foo<'a> {
x: &'a [usize],
// more here...
}
impl<'a> Foo<'a> {
pub fn new(x: &'a [usize]) -> Self {
Foo {
x, /* more here... */
}
}
}
I now need a new structure that reduces the sequence to something smaller and then builds a Foo structure over the reduced string, and since someone has to own both reduced string and Foo object, I would like to put both in a structure.
// My real Bar is slightly more complicated, but it boils down to having
// a vector it owns and a Foo over that vector.
struct Bar<'a> {
x: Vec<usize>,
y: Foo<'a>, // has a reference to &x
}
// This doesn't work because x is moved after y has borrowed it
impl<'a> Bar<'a> {
pub fn new() -> Self {
let x = vec![1, 2, 3];
let y = Foo::new(&x);
Bar { x, y }
}
}
Now, this doesn't work because the Foo object in a Bar refers into the Bar object
and if the Bar object moves, the reference will point into memory that is no longer occupied by the Bar object
To avoid this problem, the x element in Bar must sit on the heap and not move around. (I think the data in a Vec already sits happily on the heap, but that doesn't seem to help me here).
A pinned box should do the trick, I belive.
struct Bar<'a> {
x: Pin<Box<Vec<usize>>>,
y: Foo<'a>,
}
Now the structure looks like this
and when I move it, the references point to the same memory.
However, moving x to the heap isn't enough for the type-checker. It still thinks that moving the pinned box will move what it points to.
If I implement Bar's constructor like this:
impl<'a> Bar<'a> {
pub fn new() -> Self {
let v: Vec<usize> = vec![1, 2, 3];
let x = Box::pin(v);
let y = Foo::new(&x);
Bar { x, y }
}
}
I get the error
error[E0515]: cannot return value referencing local variable `x`
--> src/main.rs:22:9
|
21 | let y = Foo::new(&x);
| -- `x` is borrowed here
22 | Bar { x, y }
| ^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `x` because it is borrowed
--> src/main.rs:22:15
|
17 | impl<'a> Bar<'a> {
| -- lifetime `'a` defined here
...
21 | let y = Foo::new(&x);
| -- borrow of `x` occurs here
22 | Bar { x, y }
| ------^-----
| | |
| | move out of `x` occurs here
| returning this value requires that `x` is borrowed for `'a`
Some errors have detailed explanations: E0505, E0515.
For more information about an error, try `rustc --explain E0505`.
(Playground)
Even though the object I take a reference of sits on the heap, and doesn't move, the checker still sees me borrowing from an object that moves, and that, of course, is a no-no.
Here, you might stop and notice that I am trying to make two pointers to the same object, so Rc or Arc is an obvious solution. And it is, but I would have to change the implementation of Foo to have an Rc member instead of a reference. While I do have control of the source code for Foo, and I could update it and all the code that uses it, I am reluctant to make such a major change if I can avoid it. And I could have been in a situation where I am not in control of the Foo, so I couldn't change its implementation, and I would love to know how I would solve that situation then.
The only solution I could get to work was to get a raw pointer to x, so the type-checker doesn't see that I borrow it, and then connect x and y though that.
impl<'a> Bar<'a> {
pub fn new() -> Self {
let v: Vec<usize> = vec![1, 2, 3];
let x = Box::new(v);
let (x, y) = unsafe {
let ptr: *mut Vec<usize> = Box::into_raw(x);
let w: &Vec<usize> = ptr.as_ref().unwrap();
(Pin::new(Box::from_raw(ptr)), Foo::new(&w))
};
Bar { x, y }
}
}
Playground code here
What I don't know is if this is the right way to do it. It seems rather complicated, but perhaps it is the only way to make a structure like this in Rust? That some sort of unsafe is needed to trick the compiler. So that is the first of my questions.
The second is, if this is safe to do? Of course it is unsafe in the technical sense, but am I risking creating a reference to memory that might not be valid later? It is my impression that Pin should guarantee that the object remains where it is supposed to sit, and that the lifetime of the Bar<'a> and Foo<'a> objects should ensure that the reference doesn't out-live the vector, but once I have gone unsafe, could that promise be broken?
Update
The owning_ref crate has functionality that looks like what I need. You can create owned objects that present their references as well.
There is an OwningRef type that wraps an object and a reference, and it would be wonderful if you could have the slice in that and getting the reference wasn't seen as borrowing from the object, but obviously that isn't the case. Code such as this
use owning_ref::OwningRef;
struct Bar<'a> {
x: OwningRef<Vec<usize>, [usize]>,
y: Foo<'a>, // has a reference to &x
}
// This doesn't work because x is moved after y has borrowed it
impl<'a> Bar<'a> {
pub fn new() -> Self {
let v: Vec<usize> = vec![1, 2, 3];
let x = OwningRef::new(v);
let y = Foo::new(x.as_ref());
Bar { x, y }
}
}
you get the error
error[E0515]: cannot return value referencing local variable `x`
--> src/main.rs:22:9
|
21 | let y = Foo::new(x.as_ref());
| ---------- `x` is borrowed here
22 | Bar { x, y }
| ^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `x` because it is borrowed
--> src/main.rs:22:15
|
17 | impl<'a> Bar<'a> {
| -- lifetime `'a` defined here
...
21 | let y = Foo::new(x.as_ref());
| ---------- borrow of `x` occurs here
22 | Bar { x, y }
| ------^-----
| | |
| | move out of `x` occurs here
| returning this value requires that `x` is borrowed for `'a`
Some errors have detailed explanations: E0505, E0515.
For more information about an error, try `rustc --explain E0505`.
error: could not compile `foo` due to 2 previous errors
The reason is the same as before: I borrow a reference to x and then I move it.
There are different wrapper objects in the crate, and in various combinations they will let me get close to a solution and then snatch it away from me, because what I borrow I still cannot move later, e.g.:
use owning_ref::{BoxRef, OwningRef};
struct Bar<'a> {
x: OwningRef<Box<Vec<usize>>, Vec<usize>>,
y: Foo<'a>, // has a reference to &x
}
// This doesn't work because x is moved after y has borrowed it
impl<'a> Bar<'a> {
pub fn new() -> Self {
let v: Vec<usize> = vec![1, 2, 3];
let v = Box::new(v); // Vector on the heap
let x = BoxRef::new(v);
let y = Foo::new(x.as_ref());
Bar { x, y }
}
}
error[E0515]: cannot return value referencing local variable `x`
--> src/main.rs:23:9
|
22 | let y = Foo::new(x.as_ref());
| ---------- `x` is borrowed here
23 | Bar { x, y }
| ^^^^^^^^^^^^ returns a value referencing data owned by the current function
error[E0505]: cannot move out of `x` because it is borrowed
--> src/main.rs:23:15
|
17 | impl<'a> Bar<'a> {
| -- lifetime `'a` defined here
...
22 | let y = Foo::new(x.as_ref());
| ---------- borrow of `x` occurs here
23 | Bar { x, y }
| ------^-----
| | |
| | move out of `x` occurs here
| returning this value requires that `x` is borrowed for `'a`
Some errors have detailed explanations: E0505, E0515.
For more information about an error, try `rustc --explain E0505`.
I can get around this by going unsafe and work with a pointer, of course, but then I am back to the solution I had with Pin and pointer hacking. I strongly feel that there is a solution here, (especially because having a Box<Vec<...>> and the corresponding Vec<...> isn't adding much to the table so there must be more to the crate), but what it is is eluding me.
(I think the data in a Vec already sits happily on the heap, but that doesn't seem to help me here).
Indeed the data in a Vec does already sit on the heap, and the x: &'a [usize] in Foo is already a reference to that heap allocation; so your problem here is not (as shown in your graphics) that moving Bar would result in (the undefined behaviour of) a dangling reference.
However, what happens if the Vec were to outgrow its current allocation? It would reallocate and be moved from its present heap allocation to another—and this would result in a dangling reference. Hence the borrow checker must enforce that, so long as anything (e.g. a Foo) that borrows from the Vec exists, the Vec cannot be mutated. Yet here we already have an expressivity problem: the Rust language has no way to annotate Bar to indicate this relationship.
Your proposed unsafe solution uses <*mut _>::as_ref, whose safety documentation includes the following requirement (emphasis added):
You must enforce Rust’s aliasing rules, since the returned lifetime 'a is arbitrarily chosen and does not necessarily reflect the actual lifetime of the data. In particular, for the duration of this lifetime, the memory the pointer points to must not get mutated (except inside UnsafeCell).
This is the key bit of the compiler's safety checks that you are trying to opt out of—but because accessing Bar now requires that one uphold this requirement, you do not have a completely safe abstraction. In my view, a raw pointer would be a tad safer here because it forces one to consider the safety of every access.
For example, one issue that immediately springs to mind is that x is declared before y in Bar and therefore, upon destruction, it will be dropped first: the Vec's heap allocation will be freed while Foo still holds references into it: undefined behaviour! Simply reordering the fields would avoid this particular problem, but there would have been no such problem with raw pointers (and any attempt to dereference them in Foo's drop handler would have forced one to consider whether they were still dereferenceable at that time).
Personally, I would try to avoid self-referencing here and probably use an arena.
I think I have finally grokked ouroboros and that is an elegant solution.
You use a macro, self_referencing when defining a structure, and inside the structure you can specify that one entry borrows others. For my application, I got it to work like this:
use ouroboros::self_referencing;
#[self_referencing]
struct _Bar {
x: Vec<usize>,
#[borrows(x)]
#[covariant]
y: Foo<'this>,
}
struct Bar(pub _Bar);
The y element references x, so I specify that. I'm sure why co-/contra-varianse is needed in this particular case where there is only one lifetime, but it specififes whether other references should live longer or can live shorter than the object. I've defined the struct as _Bar and then wrapped it in Bar. This is because macro will create a new method, and I don't want the default one. At the same time I wnat to call my constructor new to stick with tradition. So I wrap the type and write my own constructor:
impl Bar {
pub fn new() -> Self {
let x: Vec<usize> = vec![1, 2, 3];
let _bar = _BarBuilder {
x,
y_builder: |x: &Vec<usize>| Foo::new(&x),
}
.build();
Bar(_bar)
}
}
I don't use the generated _Bar::new but a generated _BarBuilder object where I can specify how to get the y value from the x reference.
I have also written accessors to get the two values. There isn't anything special here.
impl Bar {
pub fn x(&self) -> &Vec<usize> {
self.0.borrow_x()
}
pub fn y(&self) -> &Foo {
self.0.borrow_y()
}
}
and with that my trivial little test case runs...
fn main() {
let bar = Bar::new();
let vec = bar.x();
for &i in vec {
println!("i == {}", i);
}
let vec = bar.y().x;
for &i in vec {
println!("i == {}", i);
}
}
This is probably the best solution so far, assuming that there are no hidden costs that I am currently unaware of.

Cannot borrow `*self` as mutable more than once at a time; in combination with HashMap

This is my code:
use std::collections::HashMap;
struct Foo {
pub map : HashMap<i32, String>
}
impl Foo {
fn foo(&mut self, x: &String) -> i32 {
// I'm planning to use/modify "x" here and also modify "self"
42
}
fn bar(&mut self) -> i32 {
let x = self.map.get_mut(&1).unwrap();
self.foo(x)
}
}
I'm getting:
error[E0499]: cannot borrow `*self` as mutable more than once at a time
--> src/main.rs:13:9
|
12 | let x = self.map.get_mut(&1).unwrap();
| -------------------- first mutable borrow occurs here
13 | self.foo(x)
| ^^^^^^^^^-^
| | |
| | first borrow later used here
| second mutable borrow occurs here
What's going on?
Modifying self and x here breaks memory safety (at least in the general situation, which is what Rust must deal with). Consider the following implementation of foo which is allowed by your signature (fixing &String to &str):
fn foo(&mut self, x: &str) -> i32 {
self.map.clear();
println!("{}", x);
42
}
But you're calling this with x being a reference to something inside of self.map. So x could be destroyed by the time it's used. That's invalid, and Rust can't prove you won't do that, because you said you might. (Kevin Anderson provides a helpful comment below if you're coming from a GC language like C# where "reference" has a different meaning.)
How to fix this depends on what you're really trying to do, though one approach would be to clone the string so it cannot be destroyed:
fn bar(&mut self) -> i32 {
let x = self.map.get(&1).unwrap().clone(); // <== now you have a copy
self.foo(&x)
}
Note this got rid of the get_mut(). It's unclear what that was for. If you need an exclusive (mut) reference into the map, then you'll need to do that separately, and you can't do that directly while also holding an exclusive reference to self for the reasons above. Remember that mut means "exclusive access," not "mutable." A side effect of having exclusive access is that mutation is allowed.
If you really need something along these lines, you need to wrap your values (String) in Arc so that you can maintain reference counts and have shared ownership. But I would first try to redesign your algorithm to avoid this.

How can I write my own swap function in Rust?

std::mem::swap has the signature:
pub fn swap<T>(x: &mut T, y: &mut T)
If I try to implement it (playground):
pub fn swap<T>(a: &mut T, b: &mut T) {
let t = a;
a = b;
b = t;
}
I get an error about the lifetimes of the two parameters:
error[E0623]: lifetime mismatch
--> src/lib.rs:4:9
|
1 | pub fn swap<T>(a: &mut T, b: &mut T) {
| ------ ------
| |
| these two types are declared with different lifetimes...
...
4 | b = t;
| ^ ...but data from `a` flows into `b` here
error[E0623]: lifetime mismatch
--> src/lib.rs:3:9
|
1 | pub fn swap<T>(a: &mut T, b: &mut T) {
| ------ ------ these two types are declared with different lifetimes...
2 | let t = a;
3 | a = b;
| ^ ...but data from `b` flows into `a` here
If I change the signature to:
pub fn swap_lt<'t, T>(mut a: &'t T, mut b: &'t T)
It compiles, but I get a warning which seems to mean that we're just swapping temporary copies:
warning: value assigned to `a` is never read
--> src/lib.rs:3:5
|
3 | a = b;
| ^
|
= note: `#[warn(unused_assignments)]` on by default
= help: maybe it is overwritten before being read?
warning: value assigned to `b` is never read
--> src/lib.rs:4:5
|
4 | b = t;
| ^
|
= help: maybe it is overwritten before being read?
Your code is not operating on temporary copies. It just swaps the references that were passed in, which does not have any effect on the values they are pointing to. This also explains why the compiler wants the lifetimes to match – reference x is pointing to the value reference y pointed to before and vice versa, which is only possible if the two references have the same lifetime.
When swapping the actual values, a different problem occurs. You first need to move one of the values to a temporary variable. However, since T is not Copy, you can't move a value out from behind a reference, since this would leave the reference invalid, which is not allowed in Rust. If you allow T: Default, you could replace the value with its default temporarily. However, if you want to implement the function for the general case, you need to resort to unsafe code. One way of doing so is using the std::ptr::read() and std::ptr::write() functions to read and write data from raw pointers:
fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
let z = read(x);
write(x, read(y));
write(y, z);
}
}
This code is trickier than it looks. The read() function returns a copy of the value without invalidating the original value, so we end up with the same non-Copy value being present in two places. We need to take care that we don't drop any of the values, which happens implicitly in many cases. For example, this implementation is wrong, since it implicitly drops the value x is initially pointing to
fn swap<T>(x: &mut T, y: &mut T) {
unsafe {
let z = read(x);
*x = read(y); // Wrong – drops the original value x is pointing to
write(y, z);
}
}
The actual implementation of swap() in the standard library uses a few optimizations:
It makes use of the std::ptr::copy_nonoverlapping() function instead of write(x, read(y)), which is implemented as a compiler intrinsic. The Rust compiler delegates this to LLVM to make sure the generated code is as efficient as possible for the target platform. Our code actually uses temporary storage for both x and y. Using copy_nonoverlapping(), temporary storage is only needed for one of the variables.
Values of size 32 or larger are swapped in blocks, so only 32 bytes of temporary storage are needed.
If you, for the sake of an exercise, don't want to use core::mem::swap or say core::ptr::swap, you could implement it as such:
pub fn swap<T>(a: &mut T, b: &mut T) {
unsafe {
let t = core::ptr::read(a);
core::ptr::copy_nonoverlapping(b, a, 1);
core::ptr::write(b, t);
}
}
Doing it using strictly safe code is not possible without having something like T: Default.
Other answers have covered unsafe implementations of swap(). A safe implementation is possible as well, but it requires additional constraints on T. For example:
pub fn swap<T: Default>(x: &mut T, y: &mut T) {
let t = std::mem::take(x);
*x = std::mem::take(y);
*y = t;
}
Here T: Default is required by std::mem::take(), which moves the value out of an &mut T reference, and leaves T::default() as replacement. A replacement is needed because the value behind the reference can and will be used again, so it must be in a valid state. For example, to move the value out of *x, we need to leave a well-defined value in *x because we will assign to *x in the subsequent line. The assignment, unaware of the previous operation, expects a valid value on the left-hand side, in order to destroy it. Leaving the old value untouched in *x would result in use-after-free and ultimately a double-free.
Another option is to require Clone:
pub fn swap<T: Clone>(x: &mut T, y: &mut T) {
let t = x.clone();
*x = y.clone();
*y = t;
}
For standard library containers this variant will be less efficient because T::clone() will perform a deep copy of the container, whereas T::default() will create an empty container without performing an allocation.
Implementing swap() without additional constraint on T requires unsafe code, as shown in other answers.

Why does the compiler error complain about multiple mutable references not dangling reference?

I am trying to understand what exactly happens when functions reborrow mutable references.
fn main() {
let mut a = String::new();
let mut b = String::new();
let aa = &mut a;
let c = my_fun(aa, &mut b);
let d = &mut a;
println!("{}", c);
}
fn my_fun<'b>(x: &'b mut String, y: &'b mut String) -> &'b mut String { y }
From my understanding the my_fun reborrows aa as &*aa whose scope would be the my_fun. But due to the lifetime bound I created in the function signature the reborrow should live at least as long as &mut b exist. So the println force the reborrow to live until it.
Shouldn't this be throwing an error of use after free because the anonymous reborrow has only scope inside my_fun? Outside of this function this reference shouldn't be valid.
But the error I get is:
error[E0499]: cannot borrow `a` as mutable more than once at a time
--> src/main.rs:7:13
|
5 | let aa= &mut a;
| ------ first mutable borrow occurs here
6 | let c = my_fun(aa, &mut b);
7 | let d = &mut a;
| ^^^^^^ second mutable borrow occurs here
8 | println!("{}", c);
| - first borrow later used
which would have made sense if the mutable reference was merely copied instead of reborrowed inside the function.
From my understanding the my_fun reborrows aa as &*aa whose scope would be the my_fun.
It's not quite that.
Let's backtrack a bit: why reborrowing?
There is a fundamental difference between &T and &mut T: &T is Copy, whereas &mut T is not even Clone. The result is that &mut T can only be moved and therefore a call such as:
let x: &mut T = /*...*/;
func(x);
Would result in x being unusable after the call. The work-around would then be to introduce a temporary:
let x: &mut T = /*...*/;
let tmp = &mut *x;
func(tmp);
This temporary would re-borrow the pointee of x, and be consumed by func.
And... that's re-borrowing! The compiler has this "temporary" creation built-in purely for ergonomics!
With that in mind, let's go back to:
From my understanding the my_fun reborrows aa as &*aa whose scope would be the my_fun.
Lifetimes are generally more a range than a point, and this is true here.
The lifetime of tmp in my example above is constrained in 2 ways:
It cannot be greater than that of x.
It cannot be less than that of func.
Which is another way of saying that it can be anything in between those bounds.
I believe you're overthinking "reborrowing" here.
The lifetime requirements you applied say that the thing being referenced by the return value will have at least the lifetime of the things being referenced by the parameters. That's true (and if it weren't provably true, this wouldn't compile). So there is no dangling reference possible.
There isn't a separate "reborrowed" reference. Borrowing is bookkeeping inside the compiler to keep track of lifetimes. There is no let x = &*aa step that actually occurs or is even particularly implied. This isn't like reference counting where memory actually changes at runtime.
Inside of my_fun, y is a reference that's scoped to the function. But the return value is scoped to the caller. (Functions would be impossible to use if this weren't true, having nothing to do with &mut.)

Resources