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

Add "as raw pointer" methods to Box #355

Closed
RalfJung opened this issue Mar 17, 2024 · 6 comments
Closed

Add "as raw pointer" methods to Box #355

RalfJung opened this issue Mar 17, 2024 · 6 comments
Labels
ACP-accepted API Change Proposal is accepted (seconded with no objections) api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api

Comments

@RalfJung
Copy link
Member

RalfJung commented Mar 17, 2024

Proposal

Problem statement

When working with raw pointers, it can be necessary to obtain raw pointers to the contents of a container in a way that multiple such pointers can alias with each other arbitrarily. For Vec, we have Vec::as_mut_ptr for that purpose, and that aliasing model interaction is even documented nowadays. However, for Box, we have no such method. One has to instead write addr_of_mut!(*bx), which works because Box is a primitive and this does not go through DerefMut. (DerefMut would be creating a reference and thus defeat the aliasing point of this.)

Motivating examples or use cases

Here's an example of code that's wrong:

use std::ptr;

fn test(mut x: Box<[u8]>) { unsafe {
    //let mut x: Vec<u8> = x.into(); // adding this line makes it well-defined
    let ptr1 = x[0..10].as_ptr();
    let ptr2 = x.as_mut_ptr().add(5); // this was meant not to invalidate `ptr1`...
    ptr::copy(ptr1, ptr2, 10);
} }

fn main() {
    test(Box::new([0; 128]));
}

This came about in rustc itself due to a refactor that replaced Vec by Box.

Solution sketch

I'm not sure how to avoid the refactoring issue, since Box can't really have self methods, so as_mut_ptr on a Box<[T]> will always call the slice method and thus create an intermediate reference. But we could at least provide methods that do the right thing and are more discoverable than the addr_of_mut! trick:

impl<T> Box<T> {
  fn as_ptr(this: &Box<T>) -> *const T { addr_of!(**this) }
  fn as_mut_ptr(this: &mut Box<T>) -> *mut T { addr_of_mut!(**this) }
}

This would also complement the existing into_raw.

Alternatives

We could do nothing and instead just document the addr_of_mut! pattern somewhere in the Box type docs.

Links and related work

Vec has as_ptr/as_mut_ptr with aliasing model guarantees.

What happens now?

This issue contains an API change proposal (or ACP) and is part of the libs-api team feature lifecycle. Once this issue is filed, the libs-api team will review open proposals as capability becomes available. Current response times do not have a clear estimate, but may be up to several months.

Possible responses

The libs team may respond in various different ways. First, the team will consider the problem (this doesn't require any concrete solution or alternatives to have been proposed):

  • We think this problem seems worth solving, and the standard library might be the right place to solve it.
  • We think that this probably doesn't belong in the standard library.

Second, if there's a concrete solution:

  • We think this specific solution looks roughly right, approved, you or someone else should implement this. (Further review will still happen on the subsequent implementation PR.)
  • We're not sure this is the right solution, and the alternatives or other materials don't give us enough information to be sure about that. Here are some questions we have that aren't answered, or rough ideas about alternatives we'd want to see discussed.
@RalfJung RalfJung added api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api labels Mar 17, 2024
@RalfJung
Copy link
Member Author

It is worth noting that this is entirely independent of rust-lang/unsafe-code-guidelines#326. It's about avoiding intermediate references on the way from Box to the raw pointer; references unambiguously have noalias so their presence can make a difference.

@scottmcm
Copy link
Member

I think we should do this regardless of it can can be done with casts, like how we have https://doc.rust-lang.org/std/ptr/fn.from_ref.html.

@RalfJung
Copy link
Member Author

RalfJung commented Aug 8, 2024

Also note that the current situation is a hazard if we ever want to make Box not a primitive type: if we apply normal DerefMut desugaring to Box, a lot of existing code will suddenly have UB due to the extra &mut T that is being introduced there. Letting people write Box::as_mut_ptr instead would avoid having to rely on the fact that Box is a primitive type and does not go through DerefMut desugaring.

@RalfJung
Copy link
Member Author

RalfJung commented Aug 8, 2024

@rust-lang/libs-api is there any way to have this nominated for an upcoming meeting, or so? :)

@scottmcm

This comment was marked as resolved.

@rustbot rustbot added the I-libs-api-nominated Indicates that an issue has been nominated for discussion during a team meeting. label Aug 8, 2024
@m-ou-se
Copy link
Member

m-ou-se commented Aug 13, 2024

We briefly discussed this in the libs-api meeting. Looks good to us. Feel free to open a tracking issue and open a PR to rust-lang/rust to add it as an unstable feature.

@m-ou-se m-ou-se added ACP-accepted API Change Proposal is accepted (seconded with no objections) and removed I-libs-api-nominated Indicates that an issue has been nominated for discussion during a team meeting. labels Aug 13, 2024
@m-ou-se m-ou-se closed this as completed Aug 13, 2024
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 25, 2024
add Box::as_ptr and Box::as_mut_ptr methods

Unstably implements rust-lang/libs-team#355. Tracking issue: rust-lang#129090.

r? libs-api
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Aug 25, 2024
add Box::as_ptr and Box::as_mut_ptr methods

Unstably implements rust-lang/libs-team#355. Tracking issue: rust-lang#129090.

r? libs-api
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Aug 25, 2024
Rollup merge of rust-lang#129091 - RalfJung:box_as_ptr, r=Amanieu

add Box::as_ptr and Box::as_mut_ptr methods

Unstably implements rust-lang/libs-team#355. Tracking issue: rust-lang#129090.

r? libs-api
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ACP-accepted API Change Proposal is accepted (seconded with no objections) api-change-proposal A proposal to add or alter unstable APIs in the standard libraries T-libs-api
Projects
None yet
Development

No branches or pull requests

4 participants