Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow types containing references to have finalizers #137

Merged
merged 1 commit into from
Nov 8, 2024

Commits on Nov 8, 2024

  1. Allow types containing references to have finalizers

    Previously FSA prevented `Gc<T>`s from having a finalizer if `T`
    (directly or indirectly) contained a reference. This made retro-fitting
    GC to large libraries difficult. It also, somewhat surprisingly,
    completely prevents finalizable nested `Gc<dyn Trait>`s (due to the
    underlying vptr being a `&'static` reference).
    
    This commit loosens this restriction, allowing FSA to interrogate drop
    method bodies (much the same as for `Send + Sync + FinalizerSafe`)
    looking for unsound uses of references.
    
    This change is based on the following observation: a reference inside of
    `T`'s drop method is safe to dereference provided it never originates
    from `T` or one of `T`'s fields. For example:
    
    ```rust
    fn drop(&mut self) {
        let a = 123;
    
        let r1 = &1; // const with 'static lifetime
        let r2 = &a; // stack-local
        let r3 = &*(unsafe { ... }); // unsafe code, all bets are off.
    
        let r4: &u64 = self.a;
        let r5: &u64 = self.b.a;
        let r6: &u64 = self.c[0]; // c: [&u64; 2]
    }
    ```
    
    In this example, `r1`, `r2`, and `r3` are allowed by FSA: `r1` and `r2`
    are sound because their referent will always be valid when the finalizer
    is called. `r3` uses unsafe code, so FSA gets out of the way here, as it
    is up to the user to ensure that this is sound themselves.
    
    `r4`, `r5`, and `r6` on the other hand are not allowed by FSA. This is
    because they are references which are obtained through field or array
    index projections into `T`. Such projections are nearly always unsound,
    so we always prevent these.
    
    This change means that we can remove the `ReferenceFree` trait, since we
    now always check for references inside a drop method. As with our
    relaxed FSA rules for `FinalizerSafe` and friends -- if for any reason
    we can't see into a type, we err on the side of caution and emit an
    error.
    jacob-hughes committed Nov 8, 2024
    Configuration menu
    Copy the full SHA
    6c5998c View commit details
    Browse the repository at this point in the history