-
Notifications
You must be signed in to change notification settings - Fork 2
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
Conversation
What does this do if I have something like: fn drop(&mut self) {
let x = self.f();
}
fn f(&self) -> &T {
&self.blah
} ? |
This is not allowed as of this PR because we can't look through |
Allow types containing references to have finalizers
I've pushed a couple of commits so that this gives us the desired behaviour. The trick is in 7bd00ae, where we negatively impl |
If you're happy, this is ready to squash. |
Please squash. |
7bd00ae
to
0704e8e
Compare
Squashed |
Fixed here 61a644a |
Please squash. |
61a644a
to
be985b8
Compare
Squashed |
Fixed here 75bf832 |
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.
Please squash. |
75bf832
to
6c5998c
Compare
Squashed |
As of [1], this is no longer part of Alloy. [1]: softdevteam/alloy#137
We can give this one another kick once softdevteam/yksom#232 lands. |
Please (a) rebase against master (c) remove the |
Not sure I understand? There's no need to rebase this, it should just merge now that softdevteam/yksom#232 has landed. I'll raise a separate PR in yksom to remove the And was there supposed to be a (b)? ;) |
Oops! (b) was "remove |
This is the Alloy PR though, there is no a) merge this. Unless I'm clearly missing something? |
Oops -- I misread the other one. Sorry! |
Previously FSA prevented
Gc<T>
s from having a finalizer ifT
(directly or indirectly) contained a reference. This made retro-fitting GC to large libraries difficult. It also, somewhat surprisingly, completely prevents finalizable nestedGc<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 fromT
or one ofT
's fields. For example:In this example,
r1
,r2
, andr3
are allowed by FSA:r1
andr2
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
, andr6
on the other hand are not allowed by FSA. This is because they are references which are obtained through field or array index projections intoT
. 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 forFinalizerSafe
and friends -- if for any reason we can't see into a type, we err on the side of caution and emit an error.