forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Perform FSA on a GC entry point's return type
Previously, when we encountered a GC FSA entry-point (e.g. `Gc::new`) we performed FSA on the argument type of that entry point. When `Gc::new` was our only entry point, this worked fine, because it would always resolve to the `T` in `Gc<T>`. However, with the addition the of `Gc::from` conversion trait entry point, we can end up being overly conservative with FSA for no good reason. Consider the following: ```rust let x: Gc<HasRef> = Gc::from(Box::new(HasRef::default())); ``` Where the argument type to this entry-point is `Box<HasRef>`, but the actual constructed `Gc` type is `Gc<HasRef>`. Using our previous approach, we would have to perform FSA on `Box<HasRef>`, even though the `Box` is never used in the context of GC. On large codebases, this lead to FSA rejecting sound `Gc<T>`s. This commit therefore tweaks FSA to check the return type of an entry-point, which should always be some `Gc<T>` (we assert! this, because if it isn't, something has gone very wrong.)
- Loading branch information
1 parent
8752468
commit bf6e042
Showing
5 changed files
with
124 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#![feature(gc)] | ||
#![feature(negative_impls)] | ||
#![allow(dead_code)] | ||
include!{"./auxiliary/types.rs"} | ||
|
||
impl<'a> Drop for HasRef<'a> { | ||
fn drop(&mut self) { | ||
use_val(self.a); // should fail | ||
} | ||
} | ||
|
||
fn main() { | ||
let _: Gc<HasRef> = Gc::from(HasRef::default()); | ||
//~^ ERROR: The drop method for `HasRef<'_>` cannot be safely finalized. | ||
let _: Gc<HasRef> = Gc::from(Box::new(HasRef::default())); | ||
//~^ ERROR: The drop method for `HasRef<'_>` cannot be safely finalized. | ||
let _: Gc<[HasRef]> = Gc::from(vec![HasRef::default()]); | ||
//~^ ERROR: The drop method for `HasRef<'_>` cannot be safely finalized. | ||
let _: Gc<[HasRef]> = Gc::from(vec![HasRef::default()].into_boxed_slice()); | ||
//~^ ERROR: The drop method for `HasRef<'_>` cannot be safely finalized. | ||
|
||
// The following should all pass. | ||
let _: Gc<u8> = Gc::from(1); | ||
let _: Gc<u8> = Gc::from(Box::new(1)); | ||
let _: Gc<[u8]> = Gc::from(vec![1, 2, 3]); | ||
let _: Gc<[u8]> = Gc::from(vec![1, 2, 3].into_boxed_slice()); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
error: The drop method for `HasRef<'_>` cannot be safely finalized. | ||
--> $DIR/gc_from.rs:13:34 | ||
| | ||
LL | use_val(self.a); // should fail | ||
| ------ | ||
| | | ||
| a finalizer cannot safely dereference this `&u64` | ||
| because it might not live long enough. | ||
... | ||
LL | let _: Gc<HasRef> = Gc::from(HasRef::default()); | ||
| ---------^^^^^^^^^^^^^^^^^- caused by trying to construct a `Gc<HasRef<'_>>` here. | ||
| | ||
= help: `Gc` may run finalizers after the valid lifetime of this reference. | ||
|
||
error: The drop method for `HasRef<'_>` cannot be safely finalized. | ||
--> $DIR/gc_from.rs:15:34 | ||
| | ||
LL | use_val(self.a); // should fail | ||
| ------ | ||
| | | ||
| a finalizer cannot safely dereference this `&u64` | ||
| because it might not live long enough. | ||
... | ||
LL | let _: Gc<HasRef> = Gc::from(Box::new(HasRef::default())); | ||
| ---------^^^^^^^^^^^^^^^^^^^^^^^^^^^- caused by trying to construct a `Gc<HasRef<'_>>` here. | ||
| | ||
= help: `Gc` may run finalizers after the valid lifetime of this reference. | ||
|
||
error: The drop method for `HasRef<'_>` cannot be safely finalized. | ||
--> $DIR/gc_from.rs:17:36 | ||
| | ||
LL | use_val(self.a); // should fail | ||
| ------ | ||
| | | ||
| a finalizer cannot safely dereference this `&u64` | ||
| because it might not live long enough. | ||
... | ||
LL | let _: Gc<[HasRef]> = Gc::from(vec![HasRef::default()]); | ||
| ---------^^^^^^^^^^^^^^^^^^^^^^^- caused by trying to construct a `Gc<[HasRef<'_>]>` here. | ||
| | ||
= help: `Gc` may run finalizers after the valid lifetime of this reference. | ||
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error: The drop method for `HasRef<'_>` cannot be safely finalized. | ||
--> $DIR/gc_from.rs:19:36 | ||
| | ||
LL | use_val(self.a); // should fail | ||
| ------ | ||
| | | ||
| a finalizer cannot safely dereference this `&u64` | ||
| because it might not live long enough. | ||
... | ||
LL | let _: Gc<[HasRef]> = Gc::from(vec![HasRef::default()].into_boxed_slice()); | ||
| ---------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- caused by trying to construct a `Gc<[HasRef<'_>]>` here. | ||
| | ||
= help: `Gc` may run finalizers after the valid lifetime of this reference. | ||
|
||
error: aborting due to 4 previous errors | ||
|