I've got a structural type with an Option<String>
field. Within a method on my optional type, I want to match on that field and extract the value into the local scope. I understand that I need to convince the borrow checker not to drop the memory pointed to within my structural type; I'm not sure how to do that.
For context, here's an obviously wrong example.
struct Cell {
data: Option<String>,
}
impl Cell {
fn match_me(&self) -> String {
match self.data {
Some(x) => x,
None => "match failed".to_owned(),
}
}
}
fn main() {
let data = Some("hello".to_owned());
let my_cell = Cell { data };
let result = my_cell.match_me();
print!("{}", result);
}
This program is obviously wrong because I'm moving the value inside of x
into the local scope, which means it will be dropped when the method returns; however, since the struct outlives the method call, the value will still be accessible elsewhere, which would produce a use after free error.
Since I want to use the Some()
value without discarding it, I figured I should reference count it. Attempt two:
use std::rc::Rc;
struct Cell {
data: Rc<Option<Rc<String>>>,
}
impl Cell {
fn match_me(&self) -> String {
let local = self.data.clone();
match *local {
Some(x) => *Rc::clone(&x),
None => "match failed".to_owned(),
}
}
}
fn main() {
let data = Rc::new(Some(Rc::new("hello".to_owned())));
let my_cell = Cell { data };
let result = my_cell.match_me();
print!("{}", result);
}
However, despite cloning these references, I'm still getting the borrow error.
Compiling playground v0.0.1 (file:///playground)
error[E0507]: cannot move out of borrowed content
--> src/main.rs:10:15
|
10 | match *local {
| ^^^^^^ cannot move out of borrowed content
11 | Some(x) => *Rc::clone(&x),
| - hint: to prevent move, use `ref x` or `ref mut x`
error[E0507]: cannot move out of borrowed content
--> src/main.rs:11:24
|
11 | Some(x) => *Rc::clone(&x),
| ^^^^^^^^^^^^^^ cannot move out of borrowed
content
Do I really have no recourse except to clone
the item itself?