Skip to content

Instantly share code, notes, and snippets.

@jdmichaud
Last active January 24, 2024 19:27
Show Gist options
  • Select an option

  • Save jdmichaud/01f7ee7a7d5261c6ba845ee3e2ee6809 to your computer and use it in GitHub Desktop.

Select an option

Save jdmichaud/01f7ee7a7d5261c6ba845ee3e2ee6809 to your computer and use it in GitHub Desktop.
Rust Smart Pointer (Cell, RefCell, Rc)
Display the source blob
Display the rendered blob
Raw
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
// 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