# Preventing \`Rc\` leaks when it references the stack

**URL:** <https://internals.rust-lang.org/t/preventing-rc-leaks-when-it-references-the-stack/1982>\
**Category:** libs\
**Created:** [May 1, 2015, 12:13pm UTC](https://internals.rust-lang.org/t/preventing-rc-leaks-when-it-references-the-stack/1982 "2015-05-01T12:13:37Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![matthieum](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matthieum/32/4023_2.png) [@matthieum](https://internals.rust-lang.org/u/matthieum)\
**Post date:** [May 1, 2015, 12:13pm UTC](https://internals.rust-lang.org/t/preventing-rc-leaks-when-it-references-the-stack/1982/1 "2015-05-01T12:13:37Z")

</div>

**Introduction**

There has been quite an outcry over the issue with `Rc` and `thread::scoped`, and two RFCs that I know of to try and “improve” the situation:

- [RFC 1085](https://github.com/rust-lang/rfcs/pull/1085): Leak and Destructor Guarantees
- [RFC 1094](https://github.com/rust-lang/rfcs/pull/1094): Guaranteed non-static destructors

However both have downsides:

- The introduction of a new marker trait (`Leak`) unfortunately introduces yet another orthogonal axis along which the world splits
- Running destructors in cycles of references is complicated (Python does not guarantee destructors will run precisely because of cycles)

Therefore I felt compelled to propose yet another alternative, one which would not affect the language, but would affect `Rc` (and `Arc`). This is a work in progress, and I was hoping the community could help me shape it up.

**Gist**

Change the bound on `Rc` and `Arc` to include `'static`, and thus forbid references to the stack.

Since that would actually a tad too restricting, it also presents a simple piece of code that shifts the lifetime check from compile-time to runtime, with minimal usage of `unsafe` code, allowing `Rc` to regain its usefulness while guaranteeing that references to the stack cannot outlive the items they reference even in the presence of cycles (and leaks).

**How to?**

I got the idea when reading Niko’s article about how `MutexGuard` did not have the issue than `JoinGuard` had because it had a runtime check and would leave the actual `Mutex` poisoned.

From then on, the question is: how to poison the stack? The implementation [can be seen on the playpen](http://is.gd/EzCRTX).

I use 3 simple structures:

```
struct BorrowGuard<'a, T: 'a>
    where T: 'a
{
    reference: &'a T,
    count: Cell<usize>,
}

struct BorrowAnchor<'a, 'b, T>
    where 'a: 'b, T: 'a
{
    reference: &'b BorrowGuard<'a, T>, // should be mut, to guarantee the anchor's unicity
}

struct BorrowRef<T>
    where T: 'static
{
    reference: &'static T,
    count: &'static Cell<usize>,
}

```

The `Guard` itself borrows the target object, guaranteeing it will outlive its references. The `Anchor` borrows the `Guard`, guaranteeing that its `Cell` will be immovable. Finally, the `Ref` strips the lifetimes, and can therefore be used in `Rc`, among other things.

_Note: at this point, one realizes that we would need 2 guard/anchor/ref triplets, as another would be needed for mutable references; I only present one such triplet here for simplicity._

It actually works pretty much like `Rc`: `Guard::count` always represents the number of existing `Ref` at any point in time (briefly out-of-sync during construction/drop of a `Ref`) and it is up to the user to guarantee that all `Ref` were dropped before the `Anchor` itself is dropped, if the user fails in that, `Anchor` aborts in its implementation of `Drop`.

**Good Points**

- _Performance_: I would expect the performance impact to be relatively minimal, the counter is only incremented/decremented when a `Ref` is formed or destroyed (which the user controls) and it is only checked when the `Anchor` is destroyed.
- _Freedom_: A user can freely use `Rc` or `Arc` without any additional burden.

**Bad Points**

- _Aesthetics_: Obviously, an aesthetics hit. One if forced to form _both_ a `Guard` and an `Anchor` before being able to have any `Ref`, and because the `Guard` outlives the `Anchor` (if only briefly) I see no easy way to make this more lightweight (as a single tuple). As such, embedding a reference to the stack into `Rc` or `Arc` requires more setup than it does today.
- _Narrowness_: Cycles are only detected if there are references to the stack, so it does not prevent all cycles.

**Comments?**

I would like to hear about the community on this. It seems to me that while there is an impact on the usability of `Rc` and `Arc`, it is worth it to prevent leaks as much as possible.

The idea of adding the `'static` to `Rc` and `Arc`, while it would have prevented the `scoped` fiasco, was not popular due to the fact that keeping references to the stack is _expected_ for efficiency reasons, however this `Guard`/`Anchor`/`Ref` dance rehabilitates it without requiring the user to reach toward `unsafe` by herself.

---

<div class="post-metadata">

**Author:** ![glaebhoerl](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/glaebhoerl/32/1978_2.png) [@glaebhoerl](https://internals.rust-lang.org/u/glaebhoerl)\
**Post date:** [May 1, 2015, 7:15pm UTC](https://internals.rust-lang.org/t/preventing-rc-leaks-when-it-references-the-stack/1982/2 "2015-05-01T19:15:49Z")

</div>

It seems to me that this could complement, rather than replace, [#1094](https://github.com/rust-lang/rfcs/pull/1094)…?

---

<div class="post-metadata">

**Author:** ![matthieum](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matthieum/32/4023_2.png) [@matthieum](https://internals.rust-lang.org/u/matthieum)\
**Post date:** [May 2, 2015, 12:23pm UTC](https://internals.rust-lang.org/t/preventing-rc-leaks-when-it-references-the-stack/1982/3 "2015-05-02T12:23:17Z")

</div>

Actually it is unclear whether it could replace [#1094](https://github.com/rust-lang/rfcs/pull/1094), it uses its basic premise (leaking `Rc` is safe if they only refer `'static` data) at the very least.

It is just that the design of `ScopedRc` with its cycle registry mechanism is rather heavyweight and I was looking for a leaner alternative, which I think I managed (though it’s unproven code…).

On the other hand, I would not be surprised if there were cases for which `ScopedRc` would be strictly superior, either because it can actually express those cases where the mechanism I present cannot or because its usage would be easier.

---

<div class="post-metadata">

**Author:** ![matthieum](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matthieum/32/4023_2.png) [@matthieum](https://internals.rust-lang.org/u/matthieum)\
**Post date:** [March 25, 2019, 8:24am UTC](https://internals.rust-lang.org/t/preventing-rc-leaks-when-it-references-the-stack/1982/4 "2019-03-25T08:24:24Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
