use std::cell::RefCell;
use std::rc::Weak;
struct Elem {
attached_elem: Weak<RefCell<Elem>>,
value: i32,
}
impl Elem {
fn borrow_mut_attached_elem(&self) -> &mut Elem {
//what should this line be?
self.attached_elem.upgrade().unwrap().borrow_mut()
}
}
fn main(){}
I have tried some similar other lines but nothing has worked so far, even the experimental cell_leak feature for RefMut.
I don't mind changing the signature of the function I just want to reduce the overhead of getting a mutable reference to the attached_elem from an Elem.
what should this line be?
There is nothing you can put in that line to (safely) satisfy the function signature - and that's for good reason. While RefCell does allow obtaining &mut T from a RefCell<T> (that's why it exists), it must guarantee that only one mutable reference exist at a time. It does so by only providing a temporary reference whose lifetime is tied to the RefMut<T> wrapper. Once the wrapper is dropped, the value is marked as no longer borrowed, so the reference must not outlive it.
If Rust were to allow you to return a naked &mut Elem, you'd be able to use the reference after the RefCell has ceased being marked as borrowed. In that case, what's to stop you from calling borrow_mut_attached_elem() again, and obtain a second mutable reference to the same Elem?
So you'll definitely need to change the signature. If you just need to give outside code temporary access to &mut Elem, the easiest way is to accept a closure that will receive it. For example:
fn with_attached_elem<R>(&self, f: impl FnOnce(&mut Elem) -> R) -> R {
let rc = self.attached_elem.upgrade().unwrap();
let retval = f(&mut *rc.borrow_mut());
retval
}
You'd call it to do something with the element, e.g.:
elem.with_attached_elem(|e| e.value += 1);
with_attached_elem takes care to return the value returned by the closure, allowing you to collect data from &mut Elem and propagate it to the caller. For example, to pick up the value of the attached element you could use:
let value = elem.with_attached_elem(|e| e.value);
Related
In this leetcode invert binary tree problem, I'm trying to borrow a node wrapped in an Rc mutably. Here is the code.
use std::rc::Rc;
use std::cell::RefCell;
impl Solution {
pub fn invert_tree(root: Option<Rc<RefCell<TreeNode>>>) -> Option<Rc<RefCell<TreeNode>>> {
let mut stack: Vec<Option<Rc<RefCell<TreeNode>>>> = vec![root.clone()];
while stack.len() > 0 {
if let Some(node) = stack.pop().unwrap() {
let n: &mut TreeNode = &mut node.borrow_mut();
std::mem::swap(&mut n.left, &mut n.right);
stack.extend(vec![n.left.clone(), n.right.clone()]);
}
}
root
}
}
If I change the line let n: &mut TreeNode to just let n = &mut node.borrow_mut(), I get a compiler error on the next line, "cannot borrow *n as mutable more than once at a time"
It seems like the compiler infers n to be of type &mut RefMut<TreeNode>, but it all works out when I explicitly say it is &mut TreeNode. Any reason why?
A combination of borrow splitting and deref-coercion causes the seemingly identical code to behave differently.
The compiler infers n to be of type RefMut<TreeNode>, because that's what borrow_mut actually returns:
pub fn borrow_mut(&self) -> RefMut<'_, T>
RefMut is a funny little type that's designed to look like a &mut, but it's actually a separate thing. It implements Deref and DerefMut, so it will happily pretend to be a &mut TreeNode when needed. But Rust is still inserting calls to .deref() in there for you.
Now, why does one work and not the other? Without the type annotation, after deref insertion, you get
let n = &mut node.borrow_mut();
std::mem::swap(&mut n.deref_mut().left, &mut n.deref_mut().right);
So we're trying to call deref_mut (which takes a &mut self) twice in the same line on the same variable. That's not allowed by Rust's borrow rules, so it fails.
(Note that the &mut on the first line simply borrows an owned value for no reason. Temporary lifetime extension lets us get away with this, even though you don't need the &mut at all in this case)
Now, on the other hand, if you do put in the type annotation, then Rust sees that borrow_mut returns a RefMut<'_, TreeNode> but you asked for a &mut TreeNode, so it inserts the deref_mut on the first line. You get
let n: &mut TreeNode = &mut node.borrow_mut().deref_mut();
std::mem::swap(&mut n.left, &mut n.right);
Now the only deref_mut call is on the first line. Then, on the second line, we access n.left and n.right, both mutably, simultaneously. It looks like we're accessing n mutably twice at once, but Rust is actually smart enough to see that we're accessing two disjoint parts of n simultaneously, so it allows it. This is called borrow splitting. Rust will split borrows on different instance fields, but it's not smart enough to see the split across a deref_mut call (function calls could, in principle, do anything, so Rust's borrow checker refuses to try to do advanced reasoning about their return value).
fn main() {
let mut name = String::from("Charlie");
let x = &mut name;
let y = x; // x has been moved
say_hello(y);
say_hello(y); // but y has not been moved, it is still usable
change_string(y);
change_string(y);
}
fn say_hello(s: &str) {
println!("Hello {}", s);
}
fn change_string(s: &mut String) {
s.push_str(" Brown");
}
When I assign x to y x has been moved. However, I would expect something with move semantics to be moved when I use it in a function. However, I can still use the reference after subsequent calls. Maybe this has to do with say_hello() taking a immutable reference but change_string() takes a mutable reference but the reference is still not moved.
You are completely right with both your reasoning and your observations. It definitely looks like things should be happening the way you describe it. However, the compiler applies some convenience magic here.
Move semantics generally apply in Rust for all types that do not implement the Copy trait. Shared references are Copy, so they are simply copied when assigned or passed to a function. Mutable references are not Copy, so they should be moved.
That's where the magic starts. Whenever a mutable reference is assigned to a name with a type already known to be a mutable reference by the compiler, the original reference is implicitly reborrowed instead of being moved. So the function called
change_string(y);
is transformed by the compiler to mean
change_string(&mut *y);
The original reference is derefenced, and a new mutable borrow is created. This new borrow is moved into the function, and the original borrow gets released once the function returns.
Note that this isn't a difference between function calls and assignments. Implicit reborrows happen whenever the target type is already known to be a mutable reference by the compiler, e.g. because the pattern has an explicit type annotation. So this line also creates an implicit reborrow, since we explicitly annotated it as a mutable reference type:
let y: &mut _ = x;
This function call on the other hand moves (and thus consumes) the mutable reference y:
fn foo<T>(_: T) {}
[...]
foo(y);
The generic type T here isn't explicitly a mutable reference type, so no implicit reborrow occurs, even though the compiler infers that the type is a mutable reference – just as in the case of your assignment let y = x;.
In some cases, the compiler can infer a generic type is a mutable reference even in the absence of an explicit type annotation:
fn bar<T>(_a: T, _b: T) {}
fn main() {
let mut i = 42;
let mut j = 43;
let x = &mut i;
let y = &mut j;
bar(x, y); // Moves x, but reborrows y.
let _z = x; // error[E0382]: use of moved value: `x`
let _t = y; // Works fine.
}
When inferring the type of the first parameter, the compiler doesn't know yet it's a mutable reference, so no implicit reborrow occurs and x is moved into the function. However, when reaching the second parameter, the compiler has already inferred that T is a mutable reference, so y is implicitly reborrowed. (This example is a good illustration why adding compiler magic to make things "just work" generally is a bad idea. Explicit is better than implicit.)
Unfortunately, this behaviour currently isn't documented in the Rust reference.
See also:
Stuff the Identity Function Does (in Rust)
Discussion of the topic on the Rust users forum
Why is the mutable reference not moved here?
I am trying to write a function that maps an Arc<[T]> into an Iterable, for use with flat_map (that is, I want to call i.flat_map(my_iter) for some other i: Iterator<Item=Arc<[T]>>).
fn my_iter<'a, T>(n: Arc<[T]>) -> slice::Iter<'a, T> {
let t: &'a [T] = &*n.clone();
t.into_iter()
}
The function above does not work because n.clone() produces an owned value of type Arc<[T]>, which I can dereference to [T] and then borrow to get &[T], but the lifetime of the borrow only lasts until the end of the function, while the 'a lifetime lasts until the client drops the returned iterator.
How do I clone the Arc in such a way that the client takes ownership of the clone, so that the value is only dropped after the client is done with the iterator (assuming no one else is using the Arc)?
Here's some sample code for the source iterator:
struct BaseIter<T>(Arc<[T]>);
impl<T> Iterator for BaseIter<T> {
type Item = Arc<[T]>;
fn next(&mut self) -> Option<Self::Item> {
Some(self.0.clone())
}
}
How do I implement the result of BaseIter(data).flat_map(my_iter) (which is of type Iterator<&T>) given that BaseIter is producing data, not just borrowing it? (The real thing is more complicated than this, it's not always the same result, but the ownership semantics are the same.)
You cannot do this. Remember, lifetimes in Rust are purely compile-time entities and are only used to validate that your code doesn't accidentally access dropped data. For example:
fn my_iter<'a, T>(n: Arc<[T]>) -> slice::Iter<'a, T>
Here 'a does not "last until the client drops the returned iterator"; this reasoning is incorrect. From the point of view of slice::Iter its lifetime parameter means the lifetime of the slice it is pointing at; from the point of view of my_iter 'a is just a lifetime parameter which can be chosen arbitrarily by the caller. In other words, slice::Iter is always tied to some slice with some concrete lifetime, but the signature of my_iter states that it is able to return arbitrary lifetime. Do you see the contradiction?
As a side note, due to covariance of lifetimes you can return a slice of a static slice from such a function:
static DATA: &'static [u8] = &[1, 2, 3];
fn get_data<'a>() -> &'a [u8] {
DATA
}
The above definition compiles, but it only works because DATA is stored in static memory of your program and is always valid when your program is running; this is not so with Arc<[T]>.
Arc<[T]> implies shared ownership, that is, the data inside Arc<[T]> is jointly owned by all clones of the original Arc<[T]> value. Therefore, when the last clone of an Arc goes out of scope, the value it contains is dropped, and the respective memory is freed. Now, consider what would happen if my_iter() was allowed to compile:
let iter = {
let data: Arc<[i32]> = get_arc_slice();
my_iter(data.clone())
};
iter.map(|x| x+1).collect::<Vec<_>>();
Because in my_iter() 'a can be arbitrary and is not linked in any way to Arc<[T]> (and can not be, actually), nothing prevents this code from compilation - the user might as well choose 'static lifetime. However, here all clones of data will be dropped inside the block, and the array it contains inside will be freed. Using iter after the block is unsafe because it now provides access to the freed memory.
How do I clone the Arc in such a way that the client takes ownership of the clone, so that the value is only dropped after the client is done with the iterator (assuming no one else is using the Arc)?
So, as follows from the above, this is impossible. Only the owner of the data determines when this data should be destroyed, and borrowed references (whose existence is always implied by lifetime parameters) may only borrow the data for the time when it exists, but borrows cannot affect when and how the data is destroyed. In order for borrowed references to compile, they need to always borrow only the data which is valid through the whole time these references are active.
What you can do is to rethink your architecture. It is hard to say what exactly can be done without looking at the full code, but in the case of this particular example you can, for example, first collect the iterator into a vector and then iterate over the vector:
let items: Vec<_> = your_iter.collect();
items.iter().flat_map(my_iter)
Note that now my_iter() should indeed accept &Arc<[T]>, just as Francis Gagné has suggested; this way, the lifetimes of the output iterator will be tied to the lifetime of the input reference, and everything should work fine, because now it is guaranteed that Arcs are stored stably in the vector for their later perusal during the iteration.
There's no way to make this work by passing an Arc<[T]> by value. You need to start from a reference to an Arc<[T]> in order to construct a valid slice::Iter.
fn my_iter<'a, T>(n: &'a Arc<[T]>) -> slice::Iter<'a, T> {
n.into_iter()
}
Or, if we elide the lifetimes:
fn my_iter<T>(n: &Arc<[T]>) -> slice::Iter<T> {
n.into_iter()
}
You need to use another iterator as return type of the function my_iter. slice::Iter<'a, T> has an associated type Item = &'a T. You need an iterator with associated type Item = T. Something like vec::IntoIter<T>. You can implement such an iterator yourself:
use std::sync::Arc;
struct BaseIter<T>(Arc<[T]>);
impl<T> Iterator for BaseIter<T> {
type Item = Arc<[T]>;
fn next(&mut self) -> Option<Self::Item> {
Some(self.0.clone())
}
}
struct ArcIntoIter<T>(usize, Arc<[T]>);
impl<T:Clone> Iterator for ArcIntoIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.0 < self.1.len(){
let i = self.0;
self.0+=1;
Some(self.1[i].clone())
}else{
None
}
}
}
fn my_iter<T>(n: Arc<[T]>) -> ArcIntoIter<T> {
ArcIntoIter(0, n)
}
fn main() {
let data = Arc::new(["A","B","C"]);
println!("{:?}", BaseIter(data).take(3).flat_map(my_iter).collect::<String>());
//output:"ABCABCABC"
}
I'm trying to implement the following code, which removes the prefix from a slice of Cow<str>'s.
fn remove_prefix(v: &mut [Cow<str>], prefix: &str) {
for t in v.iter_mut() {
match *t {
Borrowed(&s) => s = s.trim_left_matches(prefix),
Owned(s) => s = s.trim_left_matches(prefix).to_string(),
}
}
}
I have two questions:
I can't get this to compile - I've tried loads of combinations of &'s and *'s but to no avail.
Is there a better way to apply functions to a Cow<str> without having to match it to Borrowed and Owned every time. I mean it seems like I should just be able to do something like *t = t.trim_left_matches(prefix) and if t is a Borrowed(str) it leaves it as a str (since trim_left_matches allows that), and if it is an Owned(String) it leaves it as a String. Similarly for replace() it would realise it has to convert both to a String (since you can't use replace() on a str). Is something like that possible?
Question #1 strongly implies how you think pattern matching and/or pointers work in Rust doesn't quite line up with how they actually work. The following code compiles:
fn remove_prefix(v: &mut [Cow<str>], prefix: &str) {
use std::borrow::Cow::*;
for t in v.iter_mut() {
match *t {
Borrowed(ref mut s) => *s = s.trim_left_matches(prefix),
Owned(ref mut s) => *s = s.trim_left_matches(prefix).to_string(),
}
}
}
If your case, Borrowed(&s) is matched against Borrowed(&str), meaning that s is of type str. This is impossible: you absolutely cannot have a variable of a dynamically sized type. It's also counter-productive. Given that you want to modify s, binding to it by value won't help at all.
What you want is to modify the thing contained in the Borrowed variant. This means you want a mutable pointer to that storage location. Hence, Borrowed(ref mut s): this is not destructuring the value inside the Borrowed at all. Rather, it binds directly to the &str, meaning that s is of type &mut &str; a mutable pointer to a (pointer to a str). In other words: a mutable pointer to a string slice.
At that point, mutating the contents of the Borrowed is done by re-assigning the value through the mutable pointer: *s = ....
Finally, the exact same reasoning applies to the Owned case: you were trying to bind by-value, then mutate it, which cannot possibly do what you want. Instead, bind by mutable pointer to the storage location, then re-assign it.
As for question #2... not really. That would imply some kind of overloading, which Rust doesn't do (by deliberate choice). If you are doing this a lot, you could write an extension trait that adds methods of interest to Cow.
You can definitely do it.
fn remove_prefix(v: &mut [Cow<str>], prefix: &str) {
for t in v.iter_mut() {
match *t {
Cow::Borrowed(ref mut s) => *s = s.trim_left_matches(prefix),
Cow::Owned(ref mut s) => *s = s.trim_left_matches(prefix).to_string(),
}
}
}
ref mut s means “take a mutable reference to the value and call it s” in a pattern. Thus you have s of type &mut &str or &mut String. You must then use *s = in order to change what that mutable reference is pointing to (thus, change the string inside the Cow).
What is the difference between passing a value to a function by reference and passing it "by Box":
fn main() {
let mut stack_a = 3;
let mut heap_a = Box::new(3);
foo(&mut stack_a);
println!("{}", stack_a);
let r = foo2(&mut stack_a);
// compile error if the next line is uncommented
// println!("{}", stack_a);
bar(heap_a);
// compile error if the next line is uncommented
// println!("{}", heap_a);
}
fn foo(x: &mut i32) {
*x = 5;
}
fn foo2(x: &mut i32) -> &mut i32 {
*x = 5;
x
}
fn bar(mut x: Box<i32>) {
*x = 5;
}
Why is heap_a moved into the function, but stack_a is not (stack_a is still available in the println! statement after the foo() call)?
The error when uncommenting println!("{}", stack_a);:
error[E0502]: cannot borrow `stack_a` as immutable because it is also borrowed as mutable
--> src/main.rs:10:20
|
8 | let r = foo2(&mut stack_a);
| ------- mutable borrow occurs here
9 | // compile error if the next line is uncommented
10 | println!("{}", stack_a);
| ^^^^^^^ immutable borrow occurs here
...
15 | }
| - mutable borrow ends here
I think this error can be explained by referring to lifetimes. In the case of foo, stack_a (in the main function) is moved to function foo, but the compiler finds that the lifetime of the argument of the function foo, x: &mut i32, ends at end of foo. Hence, it lets us use the variable stack_a in the main function after foo returns. In the case of foo2, stack_a is also moved to the function, but we also return it.
Why doesn't the lifetime of heap_a end at end of bar?
Pass-by-value is always either a copy (if the type involved is “trivial”) or a move (if not). Box<i32> is not copyable because it (or at least one of its data members) implements Drop. This is typically done for some kind of “clean up” code. A Box<i32> is an “owning pointer”. It is the sole owner of what it points to and that's why it “feels responsible” to free the i32's memory in its drop function. Imagine what would happen if you copied a Box<i32>: Now, you would have two Box<i32> instances pointing to the same memory location. This would be bad because this would lead to a double-free error. That's why bar(heap_a) moves the Box<i32> instance into bar(). This way, there is always no more than a single owner of the heap-allocated i32. And this makes managing the memory pretty simple: Whoever owns it, frees it eventually.
The difference to foo(&mut stack_a) is that you don't pass stack_a by value. You just “lend” foo() stack_a in a way that foo() is able to mutate it. What foo() gets is a borrowed pointer. When execution comes back from foo(), stack_a is still there (and possibly modified via foo()). You can think of it as stack_a returned to its owning stack frame because foo() just borrowed it only for a while.
The part that appears to confuse you is that by uncommenting the last line of
let r = foo2(&mut stack_a);
// compile error if uncomment next line
// println!("{}", stack_a);
you don't actually test whether stack_a as been moved. stack_a is still there. The compiler simply does not allow you to access it via its name because you still have a mutably borrowed reference to it: r. This is one of the rules we need for memory safety: There can only be one way of accessing a memory location if we're also allowed to alter it. In this example r is a mutably borrowed reference to stack_a. So, stack_a is still considered mutably borrowed. The only way of accessing it is via the borrowed reference r.
With some additional curly braces we can limit the lifetime of that borrowed reference r:
let mut stack_a = 3;
{
let r = foo2(&mut stack_a);
// println!("{}", stack_a); WOULD BE AN ERROR
println!("{}", *r); // Fine!
} // <-- borrowing ends here, r ceases to exist
// No aliasing anymore => we're allowed to use the name stack_a again
println!("{}", stack_a);
After the closing brace there is again only one way of accessing the memory location: the name stack_a. That's why the compiler lets us use it in println!.
Now you may wonder, how does the compiler know that r actually refers to stack_a? Does it analyze the implementation of foo2 for that? No. There is no need. The function signature of foo2 is sufficient in reaching this conclusion. It's
fn foo2(x: &mut i32) -> &mut i32
which is actually short for
fn foo2<'a>(x: &'a mut i32) -> &'a mut i32
according to the so-called “lifetime elision rules”. The meaning of this signature is: foo2() is a function that takes a borrowed pointer to some i32 and returns a borrowed pointer to an i32 which is the same i32 (or at least a “part” of the original i32) because the the same lifetime parameter is used for the return type. As long as you hold on to that return value (r) the compiler considers stack_a mutably borrowed.
If you're interested in why we need to disallow aliasing and (potential) mutation happening at the same time w.r.t. some memory location, check out Niko's great talk.
When you pass a boxed value, you are moving the value completely. You no longer own it, the thing you passed it to does. It is so for any type that is not Copy (plain old data that can just be memcpy’d, which a heap allocation certainly can’t be). This is how Rust’s ownership model works: each object is owned in exactly one place.
If you wish to mutate the contents of the box, you should pass in a &mut i32 rather than the whole Box<i32>.
Really, Box<T> is only useful for recursive data structures (so that they can be represented rather than being of infinite size) and for the very occasional performance optimisation on large types (which you shouldn’t try doing without measurements).
To get &mut i32 out of a Box<i32>, take a mutable reference to the dereferenced box, i.e. &mut *heap_a.
The difference between passing by reference and "by box" is that, in the reference case ("lend"), the caller is responsible for deallocating the object, but in the box case ("move"), the callee is responsible for deallocating the object.
Therefore, Box<T> is useful for passing objects with responsibility for deallocating, while the reference is useful for passing objects without responsibility for deallocating.
A simple example which demonstrates these ideas:
fn main() {
let mut heap_a = Box::new(3);
foo(&mut *heap_a);
println!("{}", heap_a);
let heap_b = Box::new(3);
bar(heap_b);
// can't use `heap_b`. `heap_b` has been deallocated at the end of `bar`
// println!("{}", heap_b);
} // `heap_a` is destroyed here
fn foo(x: &mut i32) {
*x = 5;
}
fn bar(mut x: Box<i32>) {
*x = 5;
} // heap_b (now `x`) is deallocated here