I have a ‘collection of boxed terminal commands’, but now need local path result from one command for another

Thanks to @jendrikw's post I've been able to retain results.

Rust Playground

Unfortunately, I'm getting issues when the data I need to retain is a path.

Rust Playground

Does std::cell only work for primary variables?

It works for types that implement Copy, which is why you're getting this error message:

error[E0599]: the method `get` exists for reference `&Cell<PathBuf>`, but its trait bounds were not satisfied
    --> src/main.rs:54:40
     |
54   |         println!("path: {}", self.path.get());
     |                                        ^^^
     |
    ::: /playground/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/path.rs:1174:1
     |
1174 | pub struct PathBuf {
     | ------------------ doesn't satisfy `PathBuf: Copy`
     |
     = note: the following trait bounds were not satisfied:
             `PathBuf: Copy`
1 Like

Cell<T> is still usable without T: Copy. All you lose without Copy is .get() because you can’t copy the T out of the cell.

PathBuf: Default, so you can use Cell::take(), and any T[1] has access to Cell::replace() and Cell::set().
You can use those building blocks to Clone a value out of a cell:

fn clone_out<T: Clone + Default>(cell: &Cell<T>) -> T {
    let val = cell.take();
    cell.set(val.clone());
    val
}

You can replace usage of Cell::get with this function when using Clone + Default types like PathBuf/String/Vec<ClonableType>. You can even put it in an extension trait to keep method call syntax:

trait CellExt {
    type Inner;
    fn get_cloned(&self) -> Self::Inner;
}

impl<T: Clone + Default> CellExt for Cell<T> {
    type Inner = T;
    fn get_cloned(&self) -> T {
        let val = self.take();
        self.set(val.clone());
        val
    }
}

  1. where T: Sized ↩︎

4 Likes

I'm glad I can just circumvent the isssue like that.
I'll ask about the other issue in another thread.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.