How to handle `<Option<Box<_>>>` in Rust? [closed] - rust

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed last month.
Improve this question
The code:
pub struct Scope<'a> {
pub parent: Option<Box<Scope<'a>>>,
pub vars: HashMap<&'a str, Value>,
}
impl<'a> Scope<'a> {
pub fn get(&self, name: &str) -> Result<&Value, String> {
if let Some(v) = self.vars.get(name) {
Ok(v)
} else if let Some(parent) = self.parent { // <- error here
parent.get(name) // <- and here
} else {
Err(format!("{} is undefined", name))
}
}
}
And the compiler gives me this error:
error[E0507]: cannot move out of `self.parent` as enum variant `Some` which is behind a shared reference
--> src/interpreter/scope.rs:13:38
|
13 | } else if let Some(parent) = self.parent {
| ------ ^^^^^^^^^^^ help: consider borrowing here: `&self.parent`
| |
| data moved here
| move occurs because `parent` has type `Box<scope::Scope<'_>>`, which does not implement the `Copy` trait
error[E0515]: cannot return reference to local data `*parent`
--> src/interpreter/scope.rs:14:13
|
14 | parent.get(name)
| ^^^^^^^^^^^^^^^^ returns a reference to data owned by the current function
I have no idea how to fix this error. How can I fix this?
Thanks in advance.

You are transfering the ownership of the value inside self.parent. By doing let Some(parent) = self.parent now the value that was on self.parent is owned by parent. This would cause self.parent to be undefined because there can only be one owner at a time, hence the compilation error.
See ownership rules on the rust book
You can instead borrow self.parent as suggested:
impl<'a> Scope<'a> {
pub fn get(&self, name: &str) -> Result<&Value, String> {
if let Some(v) = self.vars.get(name) {
Ok(v)
} else if let Some(parent) = &self.parent { // <- borrowing self.parent
parent.get(name) // <- and here
} else {
Err(format!("{} is undefined", name))
}
}
}

Related

`&` reference, so the data it refers to cannot be borrowed as mutable

Here's the code I have:
pub struct Scope<'a> {
pub parent: Option<Box<Scope<'a>>>,
pub vars: HashMap<&'a str, Value>,
}
impl<'a> Scope<'a> {
pub fn update(&mut self, name: &'a str, v: Value) -> Option<String> {
if self.vars.contains_key(name) {
self.vars.remove(name);
self.vars.insert(name, v);
None
} else {
if let Some(parent) = &self.parent {
parent.update(name, v) // error here
} else {
Some(format!("{} is undefined", name))
}
}
}
}
Here's the error message I got from the compiler:
error[E0596]: cannot borrow `**parent` as mutable, as it is behind a `&` reference
--> src/interpreter/scope.rs:34:17
|
34 | parent.update(name, v)
| ^^^^^^^^^^^^^^^^^^^^^^ `parent` is a `&` reference, so the data it refers to cannot be borrowed as mutable
I changed let Some(parent) == &self.parent to let mut Some(parent) == &self.parent, but the compiler throws syntax errors. How can I fix this error?
By using & to borrow you take a shared reference, but you can't mutate anything behind a shared reference (except for things in an UnsafeCell but that doesn't matter here). To be able to mutate you have to take a mutable reference with &mut instead of &:
if let Some(parent) = &mut self.parent {

Rust lifetimes error with function in Mutex: "dropped here while still borrowed" [duplicate]

This question already has answers here:
What are the differences when getting an immutable reference from a mutable reference with self-linked lifetimes?
(1 answer)
Why can't I store a value and a reference to that value in the same struct?
(4 answers)
Closed 6 months ago.
I'm having trouble with Rust lifetimes. Here's a code sample:
use std::sync::Mutex
struct Bar<'a> {
handler: Mutex<Option<Box<dyn 'a + Fn()>>>
}
impl<'a> Bar<'a> {
fn new() -> Bar<'a> {
Bar {handler: Mutex::new(None)}
}
fn baz(&'a self) {
let mut handler = self.handler.lock().unwrap();
*handler = Some(Box::new(|| self.doprint()));
}
fn doprint(&self) {
println!("hello from Bar");
}
fn runhandler(&self) {
let handler = self.handler.lock().unwrap();
if let Some(handler) = handler.as_ref() {
handler();
}
}
}
fn lala() {
let bar = Bar::new();
bar.baz();
}
The purpose is so it's possible to register a handler function, which is itself able to call methods of Bar. The handler's lifetime is set so that the function needs to exist as long as Bar does.
This produces the following error:
error[E0597]: `bar` does not live long enough
--> src/chain/rpc_db.rs:68:5
|
68 | bar.baz();
| ^^^^^^^^^ borrowed value does not live long enough
69 | }
| -
| |
| `bar` dropped here while still borrowed
| borrow might be used here, when `bar` is dropped and runs the destructor for type `Bar<'_>`
I'm not sure why this error is happening given that the 'a lifetime is the lifetime of bar, so it should get dropped at the same time as bar. Although bar is borrowed for the baz call with an 'a lifetime, that call ends before the end of the function, so shouldn't interfere with the destructor. I know it's possible to solve this problem with Arcs but there's probably a better way.
Here's a more minimal example that fails with the same error:
use std::sync::Mutex
struct Bar<'a> {
handler: Mutex<Option<Box<dyn 'a + Fn()>>>
}
impl<'a> Bar<'a> {
fn new() -> Bar<'a> {
Bar {handler: Mutex::new(None)}
}
fn baz(&'a self) {
}
}
fn lala() {
let bar = Bar::new();
bar.baz();
}

Function returning reference to self can't compile, while the same code can [duplicate]

This question already has an answer here:
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
(1 answer)
Closed last year.
Given two snippets, which tries to return reference to a member value from self, I really can't understand why the one with separate function doesn't compile.
This works (godbolt):
struct Foo {
a: bool,
b: u32,
}
impl Foo {
fn get(&mut self) -> &u32 {
if self.a {
return &self.b;
}
self.a = true;
self.b = 10;
return &self.b;
}
}
While this doesn't (godbolt):
struct Foo {
a: bool,
b: u32,
}
impl Foo {
fn try_get(&self) -> Option<&u32> {
if self.a {
return Some(&self.b);
}
return None;
}
fn get(&mut self) -> &u32 {
if let Some(val) = self.try_get() {
return val;
}
self.a = true;
self.b = 10;
return &self.b;
}
}
Error:
error[E0506]: cannot assign to `self.a` because it is borrowed
--> src/lib.rs:19:9
|
14 | fn get(&mut self) -> &u32 {
| - let's call the lifetime of this reference `'1`
15 | if let Some(val) = self.try_get() {
| -------------- borrow of `self.a` occurs here
16 | return val;
| --- returning this value requires that `*self` is borrowed for `'1`
...
19 | self.a = true;
| ^^^^^^^^^^^^^ assignment to borrowed `self.a` occurs here
As I understand, it can't see, that reference at the top will be released before mutable change, but why? It can prove it without the function, why can't it do it with?
Is there any way to make function call work?
For me this really looks like a bug
I didn't see similar answer before, but after edits stackoverflow found:
Returning a reference from a HashMap or Vec causes a borrow to last beyond the scope it's in?
TLDR: yes, it is a known bug and will be fixed, and in such implementation there is no (useful) way to use function
https://github.com/rust-lang/rust/issues/21906#issuecomment-73296543

How do I consume the inner value of a Rc<RefCell<Option<_>>>? [duplicate]

This question already has answers here:
How do I move out of a struct field that is an Option?
(1 answer)
How can I swap in a new value for a field in a mutable reference to a structure?
(2 answers)
Closed 3 years ago.
I have a function of a third party library that needs ownership of a variable. Unfortunately this variable is inside a Rc<RefCell<Option<Foo>>>.
My code looks simplified like this:
use std::cell::RefCell;
use std::rc::Rc;
pub struct Foo {
val: i32,
}
fn main() {
let foo: Rc<RefCell<Option<Foo>>> = Rc::new(RefCell::new(Some(Foo { val: 1 })));
if let Some(f) = foo.into_inner() {
consume_foo(f);
}
}
fn consume_foo(f: Foo) {
println!("Foo {} consumed", f.val)
}
error[E0507]: cannot move out of an `Rc`
--> src/main.rs:11:22
|
11 | if let Some(f) = foo.into_inner() {
| ^^^ move occurs because value has type `std::cell::RefCell<std::option::Option<Foo>>`, which does not implement the `Copy` trait
I tried to use std::mem::replace(...) from How can I swap in a new value for a field in a mutable reference to a structure?:
fn main() {
let mut foo: Rc<RefCell<Option<Foo>>> = Rc::new(RefCell::new(Some(Foo { val: 1 })));
let mut foo_replaced = std::mem::replace(&mut foo.into_inner(), None);
if let Some(f) = foo_replaced.take() {
consume_foo(f);
}
}
error[E0507]: cannot move out of an `Rc`
--> src/main.rs:11:51
|
11 | let mut foo_replaced = std::mem::replace(&mut foo.into_inner(), None);
| ^^^ move occurs because value has type `std::cell::RefCell<std::option::Option<Foo>>`, which does not implement the `Copy` trait
I can't figure out how to do this properly.

Closure referring to a method of self: borrow error [duplicate]

This question already has answers here:
Mutably borrow one struct field while borrowing another in a closure
(2 answers)
Closed 5 years ago.
Here is the interesting part:
struct S1 {}
impl S1 {
pub fn new() -> Self {
S1 {}
}
pub fn foo<F>(&self, mut delegate: F) -> ()
where
F: FnMut() -> (),
{
delegate()
}
}
struct S2 {
s1: S1,
done: bool,
}
impl S2 {
pub fn new() -> Self {
S2 {
s1: S1::new(),
done: false,
}
}
fn actually_do_something(&mut self) -> () {
self.done = true
}
pub fn do_something(&mut self) -> () {
self.s1.foo(|| {
self.actually_do_something();
})
}
}
The actual error generated is:
error[E0500]: closure requires unique access to `self` but `self.s1` is already borrowed
--> src/main.rs:34:21
|
34 | self.s1.foo(|| {
| ------- ^^ closure construction occurs here
| |
| borrow occurs here
35 | self.actually_do_something();
| ---- borrow occurs due to use of `self` in closure
36 | })
| - borrow ends here
I understand why I get this error (having multiple overlapping mutable borrows of self), yet I can't find a proper way to solve it. Taking multiple deep references to my object here doesn't seem to be possible as I'm calling a self method directly.
A way of doing this is to destructure your struct. Here is a sample with your code:
pub fn do_something(&mut self) -> () {
let &mut S2 { ref mut s1, ref mut done } = self;
s1.foo(|| {
*done = true;
})
}
Playground

Resources