Skip to content

Tracking Issue for raw-pointer-to-reference conversion methods #122034

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Open
1 of 3 tasks
RalfJung opened this issue Mar 5, 2024 · 4 comments
Open
1 of 3 tasks

Tracking Issue for raw-pointer-to-reference conversion methods #122034

RalfJung opened this issue Mar 5, 2024 · 4 comments
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-libs Relevant to the library team, which will review and decide on the PR/issue.

Comments

@RalfJung
Copy link
Member

RalfJung commented Mar 5, 2024

Feature gate: #![feature(as_ref_unchecked)] (or similar)

This is a tracking issue for raw-pointer-to-reference conversion methods (rust-lang/libs-team#342).

With #106116, we have methods for almost all casts/conversions one wants to do on references and pointers, to avoid as casts and prefix operators. Just one direction is missing: turning raw pointers into references. Here we have as_ref/as_mut, but they behave different from &*ptr/&mut *ptr: they return an Option and perform a null-check. (These are the only methods on raw pointers that perform a null check.)

Public API

impl<T> *const T {
  unsafe const fn as_ref_unchecked<'a>(self) -> &'a T {
    &*self
  }
}
impl<T> *mut T {
  unsafe const fn as_ref_unchecked<'a>(self) -> &'a T {
    &*self
  }
  unsafe const fn as_mut_unchecked<'a>(self) -> &'a mut T {
    &mut *self
  }
}

Motivating examples or use cases

Some random examples from a quick grep of the rustc sources:

&mut *(out as *mut &mut dyn PrintBackendInfo)
&mut *(state as *mut &mut dyn FnMut(&[u8]) -> io::Result<()>)
&mut *(self.0 as *mut _)
&mut *(vec as *mut Vec<Library>)
&mut *(value as *mut T as *mut UnsafeCell<T>)
&mut *(s as *mut T).cast::<[T; 1]>()

The examples above then become

out.cast::<&mut dyn PrintBackendInfo>().as_mut_unchecked()
state.cast::<&mut dyn FnMut(&[u8]) -> io::Result<()>>().as_mut_unchecked()
self.0.cast().as_mut_unchecked()
vec.cast::<Vec<Library>>().as_mut_unchecked()
ptr::from_mut(value).cast::<UnsafeCell<T>>().as_mut_unchecked()
ptr::from_mut(s).cast::<[T; 1]>().as_mut_unchecked()

Unfortunately, since the as_mut name is already taken, these are all longer than the prefix variants. But they can be read left-to-right which is an advantage.

Steps / History

Unresolved Questions

  • Is there a shorter name we could use?

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html

@RalfJung RalfJung added C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-libs Relevant to the library team, which will review and decide on the PR/issue. labels Mar 5, 2024
GrigorenkoPV added a commit to GrigorenkoPV/rust that referenced this issue Mar 14, 2024
workingjubilee added a commit to workingjubilee/rustc that referenced this issue May 3, 2024
… r=workingjubilee

Implement ptr_as_ref_unchecked

Implementation of rust-lang#122034.

Prefixed the feature name with `ptr_` for clarity.

Linked const-unstability to rust-lang#91822, so the post there should probably be updated to mentions the 3 new methods when/if this PR is merged.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue May 3, 2024
… r=workingjubilee

Implement ptr_as_ref_unchecked

Implementation of rust-lang#122034.

Prefixed the feature name with `ptr_` for clarity.

Linked const-unstability to rust-lang#91822, so the post there should probably be updated to mentions the 3 new methods when/if this PR is merged.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue May 3, 2024
… r=workingjubilee

Implement ptr_as_ref_unchecked

Implementation of rust-lang#122034.

Prefixed the feature name with `ptr_` for clarity.

Linked const-unstability to rust-lang#91822, so the post there should probably be updated to mentions the 3 new methods when/if this PR is merged.
rust-timer added a commit to rust-lang-ci/rust that referenced this issue May 3, 2024
Rollup merge of rust-lang#122492 - GrigorenkoPV:ptr_as_ref_unchecked, r=workingjubilee

Implement ptr_as_ref_unchecked

Implementation of rust-lang#122034.

Prefixed the feature name with `ptr_` for clarity.

Linked const-unstability to rust-lang#91822, so the post there should probably be updated to mentions the 3 new methods when/if this PR is merged.
@Qix-
Copy link

Qix- commented Sep 4, 2024

/bikeshed

Is there a shorter name we could use?

I personally think this is fine. Follows the conventions, and most of the cases where I've reached for these methods, they've been inside macros etc. where it matters way less.

I know it's not really an option now (maybe it is?) but personally would have preferred unsafe fn as_ref() do what as_ref_unchecked() does with a try_as_ref() returning the Option<&T> (what it does now). But I wouldn't think that's possible given that it'd break a bunch of people (maybe it could be done in a new edition but not sure it's worth the effort).

workingjubilee added a commit to workingjubilee/rustc that referenced this issue Sep 10, 2024
move some const fn out of the const_ptr_as_ref feature

When a `const fn` is still `#[unstable]`, it should generally use the same feature to track its regular stability and const-stability. Then when that feature moves towards stabilization we can decide whether the const-ness can be stabilized as well, or whether it should be moved into a new feature.

Also, functions like `ptr::as_ref` (which returns an `Option<&mut T>`) require `is_null`, which is tricky and blocked on some design concerns (see rust-lang#74939). So move those to the is_null feature gate, as they should be stabilized together with `ptr.is_null()`.

Affects rust-lang#91822, rust-lang#122034, rust-lang#75402, rust-lang#74939
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Sep 10, 2024
move some const fn out of the const_ptr_as_ref feature

When a `const fn` is still `#[unstable]`, it should generally use the same feature to track its regular stability and const-stability. Then when that feature moves towards stabilization we can decide whether the const-ness can be stabilized as well, or whether it should be moved into a new feature.

Also, functions like `ptr::as_ref` (which returns an `Option<&mut T>`) require `is_null`, which is tricky and blocked on some design concerns (see rust-lang#74939). So move those to the is_null feature gate, as they should be stabilized together with `ptr.is_null()`.

Affects rust-lang#91822, rust-lang#122034, rust-lang#75402, rust-lang#74939
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Sep 10, 2024
Rollup merge of rust-lang#130164 - RalfJung:const_ptr_as_ref, r=dtolnay

move some const fn out of the const_ptr_as_ref feature

When a `const fn` is still `#[unstable]`, it should generally use the same feature to track its regular stability and const-stability. Then when that feature moves towards stabilization we can decide whether the const-ness can be stabilized as well, or whether it should be moved into a new feature.

Also, functions like `ptr::as_ref` (which returns an `Option<&mut T>`) require `is_null`, which is tricky and blocked on some design concerns (see rust-lang#74939). So move those to the is_null feature gate, as they should be stabilized together with `ptr.is_null()`.

Affects rust-lang#91822, rust-lang#122034, rust-lang#75402, rust-lang#74939
@ibraheemdev
Copy link
Member

Were deref and deref_mut ever considered? I can see how this could be confusing (and maybe ambiguous?), but these methods are the deref operations, just unsafe.

@RalfJung
Copy link
Member Author

RalfJung commented Jan 4, 2025

This doesn't deref the pointer though, so that name seems confusing to me.

The Deref trait has &Target return type just because we don't have a type that would represent a "place of type T", but the way it gets invoked by the compiler makes this still behave largely like a place. That cannot be said about a method we call directly manually.

@ibraheemdev
Copy link
Member

ibraheemdev commented Jan 4, 2025

Sure but it is equivalent to calling Deref::deref on any other pointer type, just unsafe. Similarly * returns a place to T, but is unsafe, so it is consistent in that regard. You generally do not call deref manually but it can be useful for method chaining as a postfix operation (taking advantage of auto-deref).

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
C-tracking-issue Category: An issue tracking the progress of sth. like the implementation of an RFC T-libs Relevant to the library team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

3 participants