We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Smart Pointers and Interior Mutability step 18 of 26
Rc::new_cyclic: self-reference in one step
Build entries that retain a Weak handle to themselves, then observe construction, ownership counts and cleanup.
pub fn registry(names: Vec<String>) -> Vec<(String, bool, usize)>
pub fn cyclic_facts(names: Vec<String>) -> (Vec<bool>, Vec<String>)
Use Rc::new_cyclic in the supplied make helper. Each Entry stores its
name, a self-reference me: Weak<Entry>, a seen_in_closure flag and
a shared destructor log. Keep this structure and its Drop implementation.
Create a separate entry for every input position, including repeated names. Preserve empty strings and Unicode names without modification.
What each function returns
registry returns one (name, alive, strong_count) tuple per entry in
input order. alive reports whether the stored Weak can be upgraded
after construction. Measure the strong count with only the registry's
handle retained for that entry, so every row has alive = true and count = 1.
cyclic_facts returns two vectors:
- The recorded seen_in_closure flags in input order. Each records whether the Weak supplied to the construction closure could be upgraded there.
- The actual destructor log after releasing all entries, also in input order. Explicitly drop entries in that order before reading the log.
For ["a", "b"], registry returns
[("a", true, 1), ("b", true, 1)], and cyclic_facts returns
([false, false], ["a", "b"]). Empty input gives empty vectors.
Construct the value with its weak self-reference
Rc::new_cyclic prepares the allocation, calls your closure with a
&Weak<Entry>, then initializes the value using the Entry returned
by that closure. Clone the supplied Weak into the me field.
During the closure, upgrade returns None: construction is not complete. Record that result rather than trying to unwrap it. After new_cyclic returns, the stored Weak can be upgraded while the entry has a strong owner.
This lets the self-reference be initialized together with the other fields. It avoids constructing a placeholder and then mutating the field through a shared Rc. The starter tries that direct assignment and gets E0594.
A plain Weak field does not enforce a correct self-reference by itself. Weak::new() is still a valid value of that type. The make helper must deliberately store a clone of the Weak supplied by new_cyclic.
Count before retaining an upgraded handle
A successful upgrade creates another strong Rc handle. Its lifetime matters when you inspect strong_count.
In the starter's tuple expression, the successful upgrade is a temporary that remains alive while the later tuple element reads the count. That reports two instead of one. Read the count in a separate statement before upgrading, as the exercise requires. Alternatively, release an upgraded handle before measuring; do not leave it in a local variable unintentionally.
The stored Weak does not contribute to the strong count. Immediately after this helper returns, the entry has one strong owner and one explicit Weak handle stored inside it, before any additional handles are created.
Release entries in a defined order
Weak self-references do not keep Entry values alive. Once an entry's last strong owner is released, its destructor appends the name to the log. Keep the log's own Rc alive until you have read it.
Vec does not guarantee the order in which its destructor drops elements. Do not rely on drop(entries) for the required log order. Consume the vector in a loop and call drop on each entry in sequence, then read the log.
A retained strong self-reference would instead keep the count above zero until that cycle was broken. new_cyclic provides a Weak during construction; it does not prevent later code from introducing strong ownership cycles.
Scope of the technique
This problem uses a direct weak self-reference. More complex structures can also use new_cyclic, including constructing a child that retains the supplied Weak as a back-reference to its parent. It is not a general prohibition on mutual links, nor does it initialize arbitrary graphs automatically. Plan construction order and ownership for each link.
Complete both functions and the helper. The submission must compile, match the observations and destructor order, and pass Clippy with warnings denied.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.