Last active
January 24, 2024 19:27
-
-
Save jdmichaud/01f7ee7a7d5261c6ba845ee3e2ee6809 to your computer and use it in GitHub Desktop.
Rust Smart Pointer (Cell, RefCell, Rc)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=aec552b828436a54fe2ef9337ac212f8 | |
| #![allow(warnings, unused)] | |
| use std::cell::Cell; | |
| use std::cell::RefCell; | |
| use std::rc::Rc; | |
| struct Foo { | |
| some_field: u8, | |
| } | |
| struct Bar { | |
| some_field: Cell<u8>, | |
| } | |
| fn main() { | |
| let cv = Cell::new(0); | |
| // Cell access the value through get/set | |
| cv.set(cv.get() + 1); | |
| let foo = Foo { some_field: 42 }; | |
| // --- help: consider changing this to be mutable: `mut foo` | |
| // foo.some_field += 1; | |
| // ^^^^^^^^^^^^^^^^^^^ cannot assign | |
| let bar = Bar { some_field: Cell::new(42) }; | |
| // --- bar is not mut here | |
| bar.some_field.set(bar.some_field.get() + 1); | |
| // --- still we can change the field value. | |
| let cv = Cell::new(Vec::<u8>::new()); | |
| // cv.set({ | |
| // let v = cv.get(); | |
| // ^^^ | |
| // = note: the following trait bounds were not satisfied: | |
| // `Vec<_>: Copy` | |
| // v.push(12); | |
| // v | |
| // }); | |
| // To mutate non copyable, we need RefCell | |
| let rcv = RefCell::new(Vec::new()); | |
| { | |
| let mut v = rcv.borrow_mut(); | |
| v.push(42); | |
| } | |
| // RefCell does not implement the copy trait so the... | |
| let rcv2 = rcv; | |
| // --- value moved here | |
| { | |
| // let mut v = rcv.borrow_mut(); | |
| // ^^^ value borrowed here after move | |
| // v.push(42); | |
| } | |
| // To copy references, use Rc | |
| let rcv = Rc::new(vec![24, 42]); | |
| assert_eq!(rcv[0], 24); // Rc implement Deref | |
| let rcv2 = rcv.clone(); | |
| assert_eq!(rcv2[1], 42); // multiple read only bindings | |
| // But Rc values are immutable | |
| // rcv.push(42); | |
| // ^^^ cannot borrow as mutable | |
| // To have multiple mutable references, use Rc<RefCell> ! | |
| let rcv = Rc::new(RefCell::new(Vec::new())); | |
| let rcv2 = rcv.clone(); | |
| rcv.borrow_mut().push(24); | |
| rcv2.borrow_mut().push(42); | |
| assert_eq!(rcv.borrow()[0], 24); | |
| assert_eq!(rcv2.borrow()[1], 42); | |
| { | |
| let mut cvm = rcv.borrow_mut(); | |
| // let mut cvm2 = rcv.borrow_mut(); | |
| // thread 'main' panicked at 'already borrowed: BorrowMutError', src/main.rs:74:20 | |
| // The compiler does help you there, a panic will happen during execution. | |
| } | |
| { | |
| // But you can always try first | |
| let mut cvm = rcv.borrow_mut(); | |
| cvm.push(666); | |
| if let Some(mut cvm2) = rcv.try_borrow_mut().ok() { | |
| assert!(false); | |
| } | |
| cvm.push(0); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment