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

Stdlib proposal: AsPtr, IntoRawPtr, FromRawPtr #75846

Open
Lucretiel opened this issue Aug 23, 2020 · 2 comments
Open

Stdlib proposal: AsPtr, IntoRawPtr, FromRawPtr #75846

Lucretiel opened this issue Aug 23, 2020 · 2 comments
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@Lucretiel
Copy link
Contributor

Lucretiel commented Aug 23, 2020

I'd like to propose some new conversion traits for core::convert: AsPtr, IntoRawPtr, FromRawPtr. These would be defined like so:

trait AsPtr {
    type Inner: ?Sized;
    fn as_ptr(&self) -> *const Self::Inner;
}

trait IntoRawPtr: Sized {
    type Inner: ?Sized;
    fn into_raw(self) -> *mut Self::Inner;
}

trait FromRawPtr: IntoRawPtr {
    // Safety: this must ONLY be called on a pointer that was received
    // through `into_raw`, and that pointer must immediately be discarded
    // afterwards
    unsafe fn from_raw(*mut Self::Inner) -> Self
}

These traits would be implemented for raw pointer types, as well as for smart pointer types like Box, Arc, Weak, etc.

The purpose of these traits would, obviously, be to facilitate conversion of a type into and back out of a pointer. The motivating practical use case is to make it easier to create RawWakers and associated implementations, especially through intermediate Handle types. Consider this example:

#[derive(Clone)]
struct MyWaker {
    state: Arc<State>,
}

impl MyWaker {
    fn wake(&self) { ... }
}

This would be relatively easy to create a RawWaker for, since we can directly convert the state Arc into and out of the requisite *const(), and write the vtable methods to convert it back into an Arc. However, now consider this example:

// Crate A:
#[derive(Clone)]
struct Unparker {
    state: Arc<State>
}

impl Unparker {
    fn unpark(&self) { ... }
}

// Crate B:
#[derive(Clone)]
struct MyWaker {
    state: Unparker
}

impl MyWaker {
    fn wake(&self) { self.state.unpark(); }
}

This would be impossible to create a RawWaker for, without:

  • Boxing or Arcing the Unparker (adds an unnecessary level of indirection)
  • transmuting the Unparker to and from *const() (unsafe, since it now depends on the private implementation details of Unparker).

However, with the proposed traits, if Unparker wanted to opt-in to being used in this way, it could:

impl IntoRawPtr for Unparker {
    type Inner = ();
    fn into_raw(self) -> *mut () {
        self.state.into_raw() as *mut()
    }
}

impl FromRawPtr for Unparker {
    unsafe fn from_raw(ptr: *mut ()) -> Self {
        Self { state: Arc::from_raw(ptr as *mut State) }
    }
}

This would allow the Unparker to declare its "pointer-ness" as part of its public API (without actually exposing any implementation details), enabling its use in RawWaker (and other raw pointer APIs, such as C FFI).

Alternatives:

Third party

These traits could, of course, be provided as a 3rd party crate, but I believe these traits are sufficiently "fundamental" (similar to Into/From, AsRef, etc) to warrant inclusion directly into the standard library. This would also help different, independent libraries to coordinate with each other through this trait, which is possible but more difficult (due to potential ecosystem fragmentation) with a third party crate. It's also the sort of thing that seems "too simple" to require an entire dependency crate.

Existing traits

While we could use Into / From, I don't think that those provide a strong enough contract to ensure the correct use of these, especially IntoRawPtr and FromRawPtr. Additionally, a type should only be able to be converted through a single pointer type, so having a dedicated trait with an associated type makes the most sense.

@Lucretiel Lucretiel changed the title Stdlib request: AsPtr, IntoRawPtr, FromRawPtr Stdlib proposal: AsPtr, IntoRawPtr, FromRawPtr Aug 23, 2020
@jonas-schievink jonas-schievink added C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. labels Aug 23, 2020
@scottmcm
Copy link
Member

Seems vaguely related to rust-lang/lang-team#23, though different...

@tbodt
Copy link
Contributor

tbodt commented Oct 28, 2022

Today I found myself wanting an AsPtr trait, implemented by *const T and anything that impls Borrow, because I have a hashtable that uses raw pointers as keys and I want to be able to pass any kind of pointer without having to explicitly convert. I can define the trait easily enough myself, but it would be neat to have in the stdlib.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

4 participants