rust-smart-pointers
Skill4 starsChanged 3 months agoApache-2.0View on GitHub
Understand and use Rust smart pointers including Box, Rc, Arc, RefCell, Cell, Cow, and Pin. Use when choosing heap allocation strategies, implementing shared ownership, interior mutability patterns, or working with self-referential types.
Files
Rust Smart Pointers
Based on The Rust Programming Language Ch. 15, Effective Rust, and the Nomicon.
When to Use This Skill
- Choosing between stack and heap allocation
- Implementing shared ownership (
Rc/Arc) - Interior mutability (
Cell/RefCell) - Copy-on-write patterns (
Cow) - Pinning for self-referential types (
Pin) - Understanding
Derefcoercions
Smart Pointer Overview
| Type | Ownership | Thread-safe | Mutability | Use Case |
Box<T> | Single | Yes | Via &mut | Heap allocation, recursive types |
Rc<T> | Shared | No | Immutable | Single-thread shared ownership |
Arc<T> | Shared | Yes | Immutable | Multi-thread shared ownership |
Cell<T> | Single | No | Interior | Copy types, no-borrow mutation |
RefCell<T> | Single | No | Interior | Runtime borrow checking |
Mutex<T> | Shared | Yes | Interior | Thread-safe mutable access |
RwLock<T> | Shared | Yes | Interior | Multi-reader, single-writer |
Cow<'a, T> | Borrowed or Owned | Depends | Clone-on-write | Avoid unnecessary copies |
Pin<P> | Same as P | Same as P | Same as P | Prevent moves (async, self-ref) |
Box<T>
Heap allocation with single ownership:
// Recursive type (must have known size)
enum List {
Cons(i32, Box<List>),
Nil,
}
// Large stack values
let big_array = Box::new([0u8; 1_000_000]);
// Trait objects
let drawable: Box<dyn Draw> = Box::new(Circle { radius: 5.0 });
// Transfer ownership without copy
fn process(data: Box<[u8]>) { ... }Rc<T> (Reference Counted)
Shared ownership, single-threaded:
use std::rc::Rc;
let shared = Rc::new(vec![1, 2, 3]);
let clone1 = Rc::clone(&shared); // increment ref count (cheap)
let clone2 = Rc::clone(&shared);
assert_eq!(Rc::strong_count(&shared), 3);
// Dropped when count reaches 0Weak References (Break Cycles)
use std::rc::{Rc, Weak};
struct Node {
children: Vec<Rc<Node>>,
parent: Weak<Node>, // weak to prevent cycle
}
let parent = Rc::new(Node { ... });
let weak_ref: Weak<Node> = Rc::downgrade(&parent);
// Upgrading: Weak → Option<Rc>
if let Some(strong) = weak_ref.upgrade() {
// parent still alive
}Arc<T> (Atomic Reference Counted)
Thread-safe Rc:
use std::sync::Arc;
let data = Arc::new(vec![1, 2, 3]);
let handles: Vec<_> = (0..4).map(|_| {
let data = Arc::clone(&data);
std::thread::spawn(move || {
println!("{:?}", data);
})
}).collect();Typical pattern: Arc<Mutex<T>> for shared mutable state across threads.
Cell<T>
Interior mutability for Copy types (no borrow tracking):
use std::cell::Cell;
struct Counter {
count: Cell<u32>, // can mutate through &self
}
impl Counter {
fn increment(&self) { // note: &self, not &mut self
self.count.set(self.count.get() + 1);
}
}RefCell<T>
Runtime-checked borrow rules:
use std::cell::RefCell;
let data = RefCell::new(vec![1, 2, 3]);
// Immutable borrow
let borrowed = data.borrow(); // panics if mutably borrowed
println!("{:?}", *borrowed);
drop(borrowed);
// Mutable borrow
let mut mut_borrowed = data.borrow_mut(); // panics if any borrow exists
mut_borrowed.push(4);Common pattern: Rc<RefCell<T>> for shared mutable ownership.
Cow<'a, T> (Clone on Write)
Avoids allocation when mutation isn't needed:
use std::borrow::Cow;
fn ensure_lowercase(input: &str) -> Cow<'_, str> {
if input.chars().all(|c| c.is_lowercase()) {
Cow::Borrowed(input) // no allocation
} else {
Cow::Owned(input.to_lowercase()) // allocates only when needed
}
}
// Cow implements Deref, so it works like &str
let result = ensure_lowercase("Hello");
println!("{result}"); // via Deref to &strPin<P>
Guarantees that the pointed-to value won't be moved in memory:
use std::pin::Pin;
// Pin<Box<T>> — heap-pinned value
let pinned: Pin<Box<MyFuture>> = Box::pin(MyFuture::new());
// Pin<&mut T> — stack-pinned value
let mut val = MyFuture::new();
let pinned = Pin::new(&mut val); // only works if T: Unpin
// For !Unpin types, use pin! macro (Rust 1.68+)
use std::pin::pin;
let pinned = pin!(MyFuture::new());When Pin Matters
- Async futures (self-referential across
.awaitpoints) - Intrusive data structures (nodes point to themselves)
- Any type that stores pointers to its own fields
Deref Coercions
// Smart pointers implement Deref, enabling automatic coercion:
// &Box<T> → &T
// &String → &str
// &Vec<T> → &[T]
// &Arc<T> → &T
// &Rc<T> → &T
// &Cow<'_, T> → &T
fn takes_str(s: &str) { ... }
let boxed = Box::new(String::from("hello"));
takes_str(&boxed); // Box<String> → String → str (two derefs)Reference Map
references/box-rc-arc.md— heap allocation, shared ownership, weak referencesreferences/interior-mutability.md— Cell, RefCell, Mutex, patternsreferences/pin-cow.md— Pin mechanics, Cow patterns, Deref
Key References
In this repository80 other files it gives its agents.
- a11y-accessibility-designSkill
- agentic-ui-patternsSkill
- ai-native-ui-designSkill
- ai-ui-anti-patternsSkill
- ai-ui-heuristicsSkill
- calm-technology-uiSkill
- conversion-growth-designSkill
- cross-platform-designSkill
- dark-mode-designSkill
- data-visualizationSkill
- design-systemsSkill
- design-thinking-processSkill
- error-empty-statesSkill
- ethical-design-patternsSkill
- form-uxSkill
- information-architectureSkill
- interaction-design-patternsSkill
- internationalization-uiSkill
- mobile-touch-designSkill
- modal-classes-lifecycleSkill
- modal-container-imagesSkill
- modal-dicts-queuesSkill
- modal-endpointsSkill
- modal-fundamentalsSkill
- modal-gpu-computeSkill
- modal-networkingSkill
- modal-observabilitySkill
- modal-parallel-executionSkill
- modal-sandboxesSkill
- modal-scaling-performanceSkill
- modal-schedulingSkill
- modal-secretsSkill
- modal-serversSkill
- modal-storageSkill
- modal-web-servingSkill
- modal-workspace-adminSkill
- motion-design-principlesSkill
- notifications-permissionsSkill
- onboarding-uxSkill
- rust-api-designSkill
- rust-async-programmingSkill
- rust-cargo-masterySkill
- rust-cli-applicationsSkill
- rust-clippy-lintsSkill
- rust-closures-iteratorsSkill
- rust-compiler-internalsSkill
- rust-concurrencySkill
- rust-design-patternsSkill
- rust-editionsSkill
- rust-embeddedSkill
- rust-error-handlingSkill
- rust-game-developmentSkill
- rust-lifetimes-borrowingSkill
- rust-macrosSkill
- rust-performanceSkill
- rust-rustdocSkill
- rust-rustup-toolchainSkill
- rust-testing-benchmarkingSkill
- rust-type-systemSkill
- rust-unsafe-ffiSkill
- The first 60 shown.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

