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

Use pointer offset instead of deref for A/Rc::into_raw #67339

Merged
merged 2 commits into from
Jan 16, 2020

Conversation

CAD97
Copy link
Contributor

@CAD97 CAD97 commented Dec 15, 2019

Internals thread: https://internals.rust-lang.org/t/rc-and-internal-mutability/11463/2?u=cad97

The current implementation of (A)Rc::into_raw uses the Deref::deref implementation to get the pointer-to-data that is returned. This is problematic in the proposed Stacked Borrow rules, as this only gets shared provenance over the data location. (Note that the strong/weak counts are UnsafeCell (Cell/Atomic) so shared provenance can still mutate them, but the data itself is not.) When promoted back to a real reference counted pointer, the restored pointer can be used for mutation through ::get_mut (if it is the only surviving reference). However, this mutates through a pointer ultimately derived from a &T borrow, violating the Stacked Borrow rules.

There are three known potential solutions to this issue:

  • Stacked Borrows is wrong, liballoc is correct.
  • Fully admit (A)Rc as an "internal mutability" type and store the data payload in an UnsafeCell like the strong/weak counts are. (Note: this is not needed generally since the RcBox/ArcInner is stored behind a shared NonNull which maintains shared write provenance as a raw pointer.)
  • Adjust into_raw to do direct manipulation of the pointer (like from_raw) so that it maintains write provenance and doesn't derive the pointer from a reference.

This PR implements the third option, as recommended by @RalfJung.

Potential future work: provide as_raw and clone_raw associated functions to allow the &T -> (A)Rc<T> pattern to be used soundly without creating (A)Rc from references.

@rust-highfive

This comment has been minimized.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 15, 2019
@rust-highfive

This comment has been minimized.

@CAD97
Copy link
Contributor Author

CAD97 commented Dec 16, 2019

Oh right, fat pointers...

(sorry for the number of force pushes: until I get fully moved over to my new PC the one I'm working on has some messed up dev environment and can't even build rustc fully anymore...)

@rust-highfive

This comment has been minimized.

@rust-highfive

This comment has been minimized.

@Mark-Simulacrum
Copy link
Member

r? @RalfJung

@rust-highfive

This comment has been minimized.

@RalfJung
Copy link
Member

(I'm sick and my backlog is already quite long, no promises when I'll be able to get around to this.)

@RalfJung
Copy link
Member

The general approach looks good to me, but I feel this is T-libs territory, so r? @SimonSapin

@rust-highfive rust-highfive assigned SimonSapin and unassigned RalfJung Dec 22, 2019
@SimonSapin
Copy link
Contributor

Per curl https://raw.githubusercontent.com/rust-lang/highfive/master/highfive/configs/rust-lang/rust.json|jq .groups.libs|grep @|shuf -n1

r? @sfackler

@rust-highfive rust-highfive assigned sfackler and unassigned SimonSapin Jan 15, 2020
@sfackler
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Jan 15, 2020

📌 Commit eb77f7e has been approved by sfackler

@bors bors removed the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 15, 2020
@bors bors added the S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. label Jan 15, 2020
@rust-highfive rust-highfive assigned KodrAus and unassigned sfackler Jan 15, 2020
@Dylan-DPC-zz
Copy link

Oops :D

@Dylan-DPC-zz
Copy link

r? @sfackler

@rust-highfive rust-highfive assigned sfackler and unassigned KodrAus Jan 15, 2020
@bors
Copy link
Contributor

bors commented Jan 16, 2020

⌛ Testing commit eb77f7e with merge e02c475...

bors added a commit that referenced this pull request Jan 16, 2020
Use pointer offset instead of deref for A/Rc::into_raw

Internals thread: https://internals.rust-lang.org/t/rc-and-internal-mutability/11463/2?u=cad97

The current implementation of (`A`)`Rc::into_raw` uses the `Deref::deref` implementation to get the pointer-to-data that is returned. This is problematic in the proposed Stacked Borrow rules, as this only gets shared provenance over the data location. (Note that the strong/weak counts are `UnsafeCell` (`Cell`/`Atomic`) so shared provenance can still mutate them, but the data itself is not.) When promoted back to a real reference counted pointer, the restored pointer can be used for mutation through `::get_mut` (if it is the only surviving reference). However, this mutates through a pointer ultimately derived from a `&T` borrow, violating the Stacked Borrow rules.

There are three known potential solutions to this issue:

- Stacked Borrows is wrong, liballoc is correct.
- Fully admit (`A`)`Rc` as an "internal mutability" type and store the data payload in an `UnsafeCell` like the strong/weak counts are. (Note: this is not needed generally since the `RcBox`/`ArcInner` is stored behind a shared `NonNull` which maintains shared write provenance as a raw pointer.)
- Adjust `into_raw` to do direct manipulation of the pointer (like `from_raw`) so that it maintains write provenance and doesn't derive the pointer from a reference.

This PR implements the third option, as recommended by @RalfJung.

Potential future work: provide `as_raw` and `clone_raw` associated functions to allow the [`&T` -> (`A`)`Rc<T>` pattern](https://internals.rust-lang.org/t/rc-and-internal-mutability/11463/2?u=cad97) to be used soundly without creating (`A`)`Rc` from references.
@bors
Copy link
Contributor

bors commented Jan 16, 2020

☀️ Test successful - checks-azure
Approved by: sfackler
Pushing e02c475 to master...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.