Weak References
Weak<T> is a non-owning reference to Rc/Arc data - breaks cycles via upgrade() to Option<Rc/Arc>.
Recipe
use std::rc::{Rc, Weak};
struct Node { value: i32, parent: Option<Weak<Node>>, child: Option<Rc<Node>> }When to reach for this: Parent pointers in trees/graphs without leaking Rc cycles.
Working Example
use std::rc::{Rc, Weak};
struct Owner { name: String }
struct Observer { owner: Weak<Owner> }
fn main() {
let owner = Rc::new(Owner { name: "app".into() });
let obs = Observer { owner: Rc::downgrade(&owner) };
if let Some(o) = obs.owner.upgrade() {
println!("{}", o.name);
}
}What this demonstrates:
downgradefromRctoWeakupgradereturnsNoneif owner dropped- Observer does not keep owner alive
Deep Dive
Cycles: A Rc-> B Rc-> A leak memory. Make one direction Weak. Arc::downgrade same for threads.
Gotchas
- Forgot upgrade check -
Nonemeans gone. Fix: Handle absent owner. - Upgrade keeps alive temporarily - Drop
Rcfrom upgrade promptly if not needed. - Weak without strong - Value dropped. Fix: Ensure some strong exists.
- Mutex weak patterns - Rare - usually
Arc. - upgrade in tight loop - Atomic cost on
Arc.
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Indices into arena | No refcount | Need Rc ergonomics |
| Owned graph | Clear tree ownership | Back pointers needed |
| Channels events | Decouple lifetimes | Direct observation |
FAQs
Weak Send?
Arc::Weak Send+Sync like Arc.strong_count zero?
upgrade None.cycle example?
Parent strong child, child weak parent.serde weak?
Usually skip or custom.mem leak detect?
Cycles only - use weak.downgrade clone?
Cheap Weak clone.get_mut on Rc?
Only if unique strong count.tree model?
children Vec<Rc>, parent Weak.graph?
Careful cycle design.test drop?
drop owner assert upgrade None.Related
Stack versions: This page was written for Rust 1.97.0 (edition 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, and Polars 0.46+.