variable does not live long enough in a Vec<Box<dyn trait>> - rust

I am trying to implement an algorithm like below. I don't know how to make the local variable long enough. May be my design is fully wrong.
trait Metric {
fn on_add(&mut self, _i: i32);
}
trait Update {
fn update(&mut self, _i: i32);
}
struct Metric1 {}
impl Metric for Metric1 {
fn on_add(&mut self, _i: i32) {
unimplemented!()
}
}
impl Update for Metric1 {
fn update(&mut self, _i: i32) {
unimplemented!()
}
}
struct Metric2 {}
impl Metric for Metric2 {
fn on_add(&mut self, _i: i32) {
unimplemented!()
}
}
impl Update for Metric2 {
fn update(&mut self, _i: i32) {
unimplemented!()
}
}
struct collector<'a> {
metrics: Vec<&'a mut dyn Metric>,
}
fn main() {
let mut vector_metrics: Vec<Box<dyn Metric>> = Vec::new();
let mut vector_update: Vec<Box<dyn Update>> = Vec::new();
for i in 0..2 {
if i ==0{
vector_metrics.push(Box::new(Metric1 {}));
vector_update.push(Box::new(Metric1 {}));
}
else{
vector_metrics.push(Box::new(Metric2 {}));
vector_update.push(Box::new(Metric2 {}));
}
}
let col_vector : Vec<& mut dyn Metric> = Vec::new();
for met in vector_metrics{
col_vector.push(&mut *met)
}
let coll = collector{metrics:col_vector};
}
Rust playground

vector_metrics owns the Metric objects it holds. And you are trying to create a new vector with a reference to those objects.
for met in vector_metrics moves each metric out of vector_metrics and into your met loop variable. Keeping a reference means there is no owner and the metric is dropped at the end of each loop iteration. To keep the metric owned you would need to store the owned value in col_vector:
let mut col_vector : Vec<Box<dyn Metric>> = Vec::new();
for met in vector_metrics{
col_vector.push(met);
}
Alternatively, you can iterate over vector_metrics non-destructively by taking a mutable reference to each element. This keeps ownership of the metrics in vector_metrics:
let mut col_vector : Vec<& mut dyn Metric> = Vec::new();
for met in &mut vector_metrics{
col_vector.push(&mut **met);
}

Related

Returning a mutable reference to a value behind Arc and Mutex

pub struct ForesterViewModel {
m_tree_lines: Arc<Mutex<Vec<TreeLine>>>,
}
impl ForesterViewModel {
pub fn new() -> ForesterViewModel {
ForesterViewModel {
m_tree_lines: Arc::new(Mutex::new(vec![])),
}
}
pub fn get_the_forest(&mut self) -> &mut Vec<TreeLine> {
???????????????????????????????
}
}
I need help writing the get_the_forest function. I've tried many various things but they all return compilation errors. I need to return a mutable reference to Vec<TreeLine> which is wrapped behind an Arc and a Mutex in self.m_tree_lines.
There is no way of doing this.
You create a concrete MutexGuard object that releases the mutex when it dropped when you call lock; you cannot move a reference out of the scope that contains the guard:
pub fn as_mut(&mut self) -> &Whatever {
let mut guard = self.data.lock().unwrap();
Ok(guard.deref())
drop(guard) // <--- implicitly added here, which would invalidate the ref
}
You also cannot return both the mutex guard and a reference, for more complex reasons (basically rust cannot express that), for the same reason it cannot have a reference and an object in a single structure; see the discussion on Why can't I store a value and a reference to that value in the same struct?
...so basically your best bet is one of two things:
/// Return the mutex guard itself
pub fn get_the_forest(&mut self) -> Result<MutexGuard<Vec<TreeLine>>, TreeLockError> {
Ok(self.m_tree_lines.lock()?)
}
/// Pass a function in, which patches the mutable internal value
pub fn patch_forest(&mut self, patch: impl Fn(&mut Vec<TreeLine>)) -> Result<(), TreeLockError>{
let mut guard = self.m_tree_lines.lock()?;
patch(&mut guard); // <-- patch happens while guard is still alive
Ok(())
}
Full code:
use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::PoisonError;
use std::error::Error;
use std::fmt;
use std::fmt::Formatter;
use std::ops::Deref;
#[derive(Debug, Copy, Clone)]
pub enum TreeLockError {
FailedToLock
}
impl Error for TreeLockError {}
impl fmt::Display for TreeLockError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl<T> From<PoisonError<T>> for TreeLockError {
fn from(_: PoisonError<T>) -> Self {
TreeLockError::FailedToLock
}
}
// ---
#[derive(Debug)]
pub struct TreeLine {
pub value: &'static str
}
pub struct ForesterViewModel {
m_tree_lines: Arc<Mutex<Vec<TreeLine>>>,
}
impl ForesterViewModel {
pub fn new() -> ForesterViewModel {
ForesterViewModel {
m_tree_lines: Arc::new(Mutex::new(vec![])),
}
}
pub fn get_the_forest(&mut self) -> Result<MutexGuard<Vec<TreeLine>>, TreeLockError> {
Ok(self.m_tree_lines.lock()?)
}
pub fn patch_forest(&mut self, patch: impl Fn(&mut Vec<TreeLine>)) -> Result<(), TreeLockError>{
let mut guard = self.m_tree_lines.lock()?;
patch(&mut guard);
Ok(())
}
}
fn main() -> Result<(), Box<dyn Error>> {
let mut vm = ForesterViewModel::new();
{
let mut trees = vm.get_the_forest()?;
trees.push(TreeLine{ value: "one"});
trees.push(TreeLine{ value: "two"});
} // <--- Drop the mutable reference here so you can get it again later
// Patch
vm.patch_forest(|trees| {
trees.push(TreeLine{ value: "three"});
});
// ...
let trees = vm.get_the_forest()?;
println!("{:?}", trees.deref());
Ok(())
}

How to iterate over an Rc<RefCell<T>> that returns raw mutable references

I have a Vec<Rc<RefCell<MyStruct>>> member on a struct and I have an external library function that expects to be handed an Iterator with an Item that is a &'a mut dyn LibTrait which I have as a member inside MyStruct. I can't figure out how to get a raw &mut from out of the Rc<RefCell<MyStruct>> in my iterator even though I know the Vec member that holds it will stick around for longer than either the iterator or the function that gets passed the iterator.
The library looks like this:
struct Lib {}
trait LibTrait {
fn run(&mut self);
}
impl Lib {
pub fn lib_func<'a, Iter>(&mut self, trait_iter: Iter)
where
Iter: Iterator<Item = &'a mut dyn LibTrait>,
{
...
}
}
Here's my latest attempt where I tried to create a temp Vec to hold RefMut's to all the MyStructs so that those refs are owned for the whole time that the &mut would be inside the iterator and lib function. (This code complains about "cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements".)
struct TraitImpl {
dummy: f32,
}
impl LibTrait for TraitImpl {
fn run(&mut self) {
self.dummy += 1.0;
}
}
struct MyStruct {
my_impl: TraitImpl,
num: f32,
}
type MutStructSlice<'a> = &'a mut [&'a mut MyStruct];
struct TraitIterator<'a> {
my_structs: MutStructSlice<'a>,
index: usize,
}
impl<'a> TraitIterator<'a> {
fn new(my_structs: MutStructSlice<'a>) -> Self {
Self {
my_structs,
index: 0,
}
}
}
impl<'a> Iterator for TraitIterator<'a> {
type Item = &'a mut dyn LibTrait;
fn next(&mut self) -> Option<&'a mut dyn LibTrait> {
if self.index >= self.my_structs.len() {
return None;
}
Some(&mut self.my_structs[self.index].my_impl)
}
}
struct Data {
data: Vec<Rc<RefCell<MyStruct>>>,
lib: Lib,
}
impl Data {
fn do_stuff(&mut self) {
let mut struct_refs: Vec<RefMut<MyStruct>> = self
.data
.iter_mut()
.map(|s_rc| s_rc.borrow_mut())
.collect();
let mut structs_raw_refs: Vec<&mut MyStruct> =
struct_refs.iter_mut().map(|s_ref| &mut **s_ref).collect();
self.lib.lib_func(TraitIterator::new(&mut structs_raw_refs));
}
}
Here's the playground
Is there some way around this given that I can't change the library and I need to have Rc<RefCell<>>'s to the data?
I think you're overcomplicating this. You don't need a custom iterator, you can do this with .map():
fn do_stuff(&mut self) {
let mut struct_refs: Vec<RefMut<MyStruct>> = self.data
.iter_mut()
.map(|s_rc| s_rc.borrow_mut())
.collect();
self.lib.lib_func(struct_refs.iter_mut().map(|s_ref| &mut s_ref.my_impl as &mut dyn LibTrait));
}
You get the error you did because implementing Iterator for &mut T is inherently unsafe. See How to implement Iterator yielding mutable references.

Specify that lifetime of argument lasts for function call

I have a trait with a function that takes a reference to an iterator:
#[derive(Clone)]
struct Dog {
name: &'static str,
}
trait DogListAction<'a, I>
where
I: Iterator<Item = &'a Dog>,
{
fn on_dog_list(&mut self, dog_list: I);
}
struct DogListActionExample {}
impl<'a, I> DogListAction<'a, I> for DogListActionExample
where
I: Iterator<Item = &'a Dog>,
{
fn on_dog_list(&mut self, dog_list: I) {
for dog in dog_list {
println!("{}", dog.name);
}
}
}
fn main() {
let dogs = vec![Dog { name: "Pluto" }, Dog { name: "Lilly" }];
let mut action_example = DogListActionExample {};
let mut dog_list_actions: Vec<Box<DogListAction<_>>> = vec![Box::new(action_example)];
loop {
let dog_clone = dogs.clone();
for dog_list_action in &mut dog_list_actions {
dog_list_action.on_dog_list(dog_clone.iter());
}
}
}
playground
It does not take any reference to the elements, so there is no need for it to last for more time than the function call.
Due to my limited understanding of lifetimes, I do not know yet how to express this. Calling this function causes a compilation error:
error[E0597]: `dog_clone` does not live long enough
--> src/main.rs:33:41
|
33 | dog_list_action.on_dog_list(dog_clone.iter());
| ^^^^^^^^^ borrowed value does not live long enough
34 | }
35 | }
| - `dog_clone` dropped here while still borrowed
36 | }
| - borrowed value needs to live until here
I guess the borrow checker thinks that data in dog_clone may be referenced after the function ends, but this is not the case.
The problem here is that the code can potentially save short-lived references to dog_clone elements in the longer-lived dog_list_actions. We need to tell the compiler that we will not be saving references the iterator produces. It can be done like this:
trait DogListAction {
fn on_dog_list<'a, I>(&'a mut self, dog_list: I)
where
I: Iterator<Item = &'a Dog>;
}
Now Item's can live for the duration of on_dog_list call. In the original code they must live for longer duration.
But this code creates another problem: we can't box the trait DogListAction anymore as it includes generic function. The usual approach here is to use a trait object:
trait DogListAction {
fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>);
}
Note the second 'a in Box<dyn Iterator<Item = &'a Dog> + 'a>. Rust adds a 'static trait bound to boxed trait objects by default and we don't want 'static here.
#[derive(Clone)]
struct Dog {
name: &'static str,
}
trait DogListAction {
fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>);
}
struct DogListActionExample {}
impl DogListAction for DogListActionExample {
fn on_dog_list<'a>(&'a mut self, dog_list: Box<dyn Iterator<Item = &'a Dog> + 'a>) {
for dog in dog_list {
println!("{}", dog.name);
}
}
}
fn main() {
let dogs = vec![Dog { name: "Pluto" }, Dog { name: "Lilly" }];
let action_example = DogListActionExample {};
let mut dog_list_actions: Vec<Box<DogListAction>> = vec![Box::new(action_example)];
{
let dogs_clone = dogs.clone();
for dog_list_action in &mut dog_list_actions {
dog_list_action.on_dog_list(Box::new(dogs_clone.iter()));
}
}
}
Playground

Declaring a vector of trait objects with a lifetime parameter

I have a Widget trait parametrised on a context type:
trait Widget<C> {
fn f<'a>(&self, ctx: &'a mut C);
}
Some widgets whose context types are the same, but contain references so are parameterised:
struct Ctxt<'c> {
data: &'c u32,
}
struct W1 {}
struct W2 {}
impl<'c> Widget<Ctxt<'c>> for W1 { // and W2
fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
unimplemented!()
}
}
I have a multi-widget which wants to store several of these:
struct WV {
widgets: Vec<Box<Widget<Ctxt<????>>>>,
}
impl<'c> Widget<Ctxt<'c>> for WV {
fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
for w in &self.widgets {
w.f(ctx);
}
}
}
It looks like I need a Vec<Box<Widget<for<'c> Ctxt<'c>>>>; but you can't do that! Alternatively, only specifying the lifetime in the definition of f:
impl Widget<Ctxt> for W {
fn f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
unimplemented!()
}
}
This doesn't work either (missing lifetime parameter for Ctxt).
The purpose of the context is to pass a mutable reference to something long-lived which is only needed during f; the &mut reference can't be stored in W1 etc. I don't really want to specify any lifetimes for Ctxt.
How can I store multiple implementers of the trait, which allow passing in a context containing references?
After a night's sleep, I think I have an answer. I can defer the selection of the Ctxt lifetime by indirecting through a new trait CtxtWidget, and impl<'c> Widget<Ctxt<'c>> for the new trait:
trait Widget<C> {
fn f<'a>(&self, ctx: &'a mut C);
}
struct W1 {}
struct W2 {}
struct Ctxt<'c> {
data: &'c u32,
}
trait CtxtWidget {
fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>);
}
impl CtxtWidget for W1 {
fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
unimplemented!()
}
}
impl CtxtWidget for W2 {
fn ctxt_f<'a, 'c>(&self, ctx: &'a mut Ctxt<'c>) {
unimplemented!()
}
}
impl<'c> Widget<Ctxt<'c>> for Box<CtxtWidget> {
fn f<'a>(&self, ctx: &'a mut Ctxt<'c>) {
self.ctxt_f(ctx);
}
}
struct WV {
pub widgets: Vec<Box<CtxtWidget>>,
}
fn main() {
let mut wv = WV{widgets: Vec::new()};
wv.widgets.push(Box::new(W1{}));
wv.widgets.push(Box::new(W2{}));
let u = 65u32;
let mut ctxt = Ctxt{data: &u};
for widget in &wv.widgets {
widget.f(&mut ctxt);
}
}
(playground)
In effect CtxtWidget is roughly equivalent to for<'c> Widget<Ctxt<'c>>.
I'd still be interested in any other solutions (including intrusive changes if there's a better way to do this).

Borrows and ownership of object on thread

Sorry for newbie question. The error here is
<anon>:30:5: 30:17 error: cannot borrow immutable borrowed content as mutable
<anon>:30 routing_node.put(3);
^^^^^^^^^^^^
I have tried many things to work around this but know for sure this is a simple error. Any help much appreciated.
use std::thread;
use std::thread::spawn;
use std::sync::Arc;
struct RoutingNode {
data: u16
}
impl RoutingNode {
pub fn new() -> RoutingNode {
RoutingNode { data: 0 }
}
pub fn run(&self) {
println!("data : {}", self.data);
}
pub fn put(&mut self, increase: u16) {
self.data += increase;
}
}
fn main() {
let mut routing_node = Arc::new(RoutingNode::new());
let mut my_node = routing_node.clone();
{
spawn(move || {my_node.run(); });
}
routing_node.put(3);
}
Arc isn't allowing to mutate of it's inner state, even if container is marked as mutable. You should use one of Cell, RefCell or Mutex. Both Cell and RefCell are non-threadsafe so you should use Mutex (last paragraph in docs).
Example:
use std::thread::spawn;
use std::sync::Mutex;
use std::sync::Arc;
struct RoutingNode {
data: u16,
}
impl RoutingNode {
pub fn new() -> Self { RoutingNode { data: 0, } }
pub fn run(&self) { println!("data : {}" , self.data); }
pub fn put(&mut self, increase: u16) { self.data += increase; }
}
fn main() {
let routing_node = Arc::new(Mutex::new(RoutingNode::new()));
let my_node = routing_node.clone();
let thread = spawn(move || { my_node.lock().unwrap().run(); });
routing_node.lock().unwrap().put(3);
let _ = thread.join();
}
Playpen

Resources