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

internal UnsafeCell causes references to be dropped immediately #36063

Closed
vitiral opened this issue Aug 28, 2016 · 4 comments
Closed

internal UnsafeCell causes references to be dropped immediately #36063

vitiral opened this issue Aug 28, 2016 · 4 comments

Comments

@vitiral
Copy link
Contributor

vitiral commented Aug 28, 2016

This has been driving me crazy and I have finally found the root cause of the bug.

# just updated today
$ rustup toolchain list
stable-x86_64-unknown-linux-gnu
nightly-2016-06-16-x86_64-unknown-linux-gnu
nightly-2016-07-07-x86_64-unknown-linux-gnu
nightly-2016-08-18-x86_64-unknown-linux-gnu
nightly-x86_64-unknown-linux-gnu (default)

I have tried to compile with all of these versions, so I can be pretty sure that this bug is NOT a regression.

The source code that details the bug is here:
https://github.com/vitiral/notes/tree/rust_bug/rust/lifesucks/src

You can see I have created 3 versions of roughly the same code in increasing complexity:

  • simple.rs contains an ultra simple version of what I am trying to do: have some data behind a pool that allocates to a mutex. In this case, it doesn't even support dynamic types. This compiles
  • complex.rs is a more complete version of the same thing and this also compiles
  • very_complex.rs is almost idential to complex.rs but it hides it's data behind an UnsafeCell. this does not compile

For very_complex.rs the compiler gives these errors:

src/very_complex.rs:67:18: 67:33 error: `unwrapped_alloc` does not live long enough
src/very_complex.rs:67     let locked = unwrapped_alloc.try_lock();
                                        ^~~~~~~~~~~~~~~
src/very_complex.rs:64:41: 79:2 note: reference must be valid for the block suffix following statement 1 at 64:40...
src/very_complex.rs:64     let pool = Pool::new(&mut data[..]);
                                                               ^
src/very_complex.rs:66:44: 79:2 note: ...but borrowed value is only valid for the block suffix following statement 3 at 66:43
src/very_complex.rs:66     let unwrapped_alloc = alloced.unwrap();
                                                                  ^
src/very_complex.rs:71:24: 71:25 error: `v` does not live long enough
src/very_complex.rs:71         Ok(v) => match v.try_lock() {

even though that section of code looks like this:

let alloced = pool.alloc::<u32>();
let unwrapped_alloc = alloced.unwrap();
let locked = unwrapped_alloc.try_lock();
let unwrapped_locked = locked.unwrap();
assert_eq!(unwrapped_locked.deref(), &0x01010101);

In other words, there is no way this is because of #15023 (also, it works fine in the other versions).

It would be great if someone could take a look, this has been driving me absolutely crazy today.

@arielb1
Copy link
Contributor

arielb1 commented Aug 28, 2016

This is because you are taking an &'pool Mutex, while Mutex is a pointer, as an argument. This requires the struct Mutex returned from alloc to live as long as the pool, which is impossible because it only lives like a local variable.

The way to fix this is to stop requiring a &'pool Mutex<'pool> everywhere. The reason this works without the UnsafeCell is because variance meant that the Pool<'pool> was as good as a Pool<'a>.

@arielb1 arielb1 closed this as completed Aug 28, 2016
@vitiral
Copy link
Contributor Author

vitiral commented Aug 28, 2016

Hey @arielb1, thanks for taking a look at this.

I don't understand several points you are making though.

you are taking an &'pool Mutex, while Mutex is a pointer, as an argument

When is Mutex a pointer? Do you mean with MutexGuard?

This requires the struct Mutex returned from alloc to live as long as the pool, which is impossible because it only lives like a local variable

but the Pool is a local variable too, I don't understand why it can't just live as long as the pool (I am even telling it to live as long as the pool with the lifetime)

The way to fix this is to stop requiring a &'pool Mutex<'pool> everywhere

I'm not sure what I should replace it with. Mutex references Pool, so it needs to share it's lifetime -- doesn't it? I'm not sure how else to express this.

Please help, I am really confused.

@vitiral
Copy link
Contributor Author

vitiral commented Aug 28, 2016

nevermind, I have found a way around it -- I just don't use UnsafeCell at all. I added the file complex_ptr.rs to show how I am getting around it.

@vitiral
Copy link
Contributor Author

vitiral commented Aug 28, 2016

I really do still think this is a bug -- try to get very_comlex.rs to compile and I don't think it is possible (if it is I would love to see, since I think it would help me understand lifetimes that much better). Can someone else take a quick look at it or get it to compile?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants