-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Tracking issue for <*mut T, *const T>::{as_ref, as_mut_ref} #27780
Comments
People really really really _really_ like using Options for anything that "might" be. Historically I recall you arguing against it because raw pointers can be invalid in so many other ways. But that seems immaterial here. When you're calling this you're asserting that the only way it can be invalid is if it's Surely this is something FFI encounters a lot? |
I have personally never felt the need to use these functions, I've always just done |
This is actually really useful in concurrent lock free hashtables where the hash points to an atomic pointer. This means you end up iteratoring across a list of atomics [1], which is a nice clean recursive operation with the old Option syntax. I guess it is just syntax, but here mapping the Option vaule is pretty nice. [1] Data Structure described: https://www.youtube.com/watch?v=HJ-719EGIts |
I find them quite frequently useful, and it appears that others do as well. To be honest, I'm not sure what the justification for removing it is anyway. If anything we should be adding more sugar to raw pointers, not removing what already exists. |
I came across this issue while working on Gecko/Servo layout bindings, which involves heavy FFI usage. My first implementation looked like this:
With as_ref, I was able to transform it to:
Which is a heck of a lot nicer. |
🔔 This issue is now entering its cycle final comment period to be handled in 1.8 🔔 The libs team is somewhat on the fence about this method, and we figured that the FCP can serve as a good opportunity to foster discussion around these methods! |
Most of the discussion in this thread so far is about why they are useful and convenient. Can you elaborate on the rationale for removing them? |
I think that I'm probably one of the bigger proponents for their removal, so certainly! I certainly agree that these methods can be nice to use from time to time, but I have personally never actually found a case where I ended up using them in the long run. I'm a little unsettled by the only invalid pointer is the null pointer (when there's a whole bunch of other invalid values), and to me this kinda sticks out as an initial attempt at "nicer I would be more comfortable if we had a comprehensive story about ergonomically working with raw pointers. @gankro's initial stab with raw-rs I think is a great start here. Starting with just Now I definitely don't feel super strongly either way on this, however. If others find these methods quite useful, then I'd be fine stabilizing. |
I think you’re looking at this differently than the people who use these methods. The point is that in some cases, null is not invalid, it’s used to represent the absence of something. (Some other invariant is used to make sure other invalid pointers don’t occur, for example "this field is private and only ever set to Now, you could argue that people should not use
raw-rs looks nice but largely unrelated. I don’t see anything related to null-as-an-expected-value in it. |
The main use case is handling return Null pointers. But I understand the concern with other forms of pointer invalidation. If raw-rs pans out could it be integrated into the Option return value? Or is returning invalid pointers something that stabilizing on could potentially bite the project? (I can't think of a use case for this but I also haven't had coffee yet this morning). |
Yeah, as @SimonSapin noted, it's not really an issue of pointer validity - when working over an FFI, you kinda need to assume that returned struct pointers (which are generally opaque) are always valid. Rather, the issue here is nullability, which is represented with Option<> in Rust and nullptr in C/C++. FFIs need to return nullable values all the time (see the Gecko_GetRootNode example above), and so a more-convenient mapping between nullptr and Option reduces the impedance mismatch between the two. |
Does this require that Rust's alignment always matches C's alignment? A Note that the Rust alignment of a type must always be greater or equal to the C required alignment in order for So, this issue may result in locking Rust into having exactly the same alignment requirements as the C ABI. |
The duality of The platform-specific alignment of primitives is also specified in the nomicon -- https://doc.rust-lang.org/stable/nomicon/repr-rust.html (first paragraph):
|
Why do these methods take |
This is very useful in |
This isn't true: it can be incorrect/undefined behaviour to convert an unaligned pointer to a reference. (In any case, I believe |
The libs team discussed this during triage yesterday, and the conclusion was pretty inconclusive. Some points brought up were:
Overall we weren't able to reach a conclusion on this, so I'm going to nominate it for discussion to move into FCP again next cycle. |
One minor point is that the already stabilized method |
🔔 This issue is reentering its cycle-long final comment period 🔔 We still haven't quite decided on a great name for these methods just yet, but it's something we can perhaps decide during FCP! |
I haven't seen any answer or discussion about my question above:
In contrast, the other standard methods on pointers all take |
I suspect it was the old convention of trying to be "less unsafe" when returning a lifetime. Nowadays we'd just switch this back to |
If they take |
To what extent does converting a pointer to a reference with these methods affect aliasing requirements on references? |
Same as dereferencing raw pointers? |
@archshift these sort of |
The libs team discussed this during triage yesterday and the conclusion was to stabilize as-is with a minor tweak to the by-value-self method. The new signatures will be: unsafe fn as_ref<'a>(self) -> Option<&'a T>;
unsafe fn as_mut<'a>(self) -> Option<&'a mut T>; We ended up concluding that the Thanks again for the discussion everyone! |
\o/ |
The second should have a |
@shepmaster ah yes, of course! |
This commit applies all stabilizations, renamings, and deprecations that the library team has decided on for the upcoming 1.9 release. All tracking issues have gone through a cycle-long "final comment period" and the specific APIs stabilized/deprecated are: Stable * `std::panic` * `std::panic::catch_unwind` (renamed from `recover`) * `std::panic::resume_unwind` (renamed from `propagate`) * `std::panic::AssertUnwindSafe` (renamed from `AssertRecoverSafe`) * `std::panic::UnwindSafe` (renamed from `RecoverSafe`) * `str::is_char_boundary` * `<*const T>::as_ref` * `<*mut T>::as_ref` * `<*mut T>::as_mut` * `AsciiExt::make_ascii_uppercase` * `AsciiExt::make_ascii_lowercase` * `char::decode_utf16` * `char::DecodeUtf16` * `char::DecodeUtf16Error` * `char::DecodeUtf16Error::unpaired_surrogate` * `BTreeSet::take` * `BTreeSet::replace` * `BTreeSet::get` * `HashSet::take` * `HashSet::replace` * `HashSet::get` * `OsString::with_capacity` * `OsString::clear` * `OsString::capacity` * `OsString::reserve` * `OsString::reserve_exact` * `OsStr::is_empty` * `OsStr::len` * `std::os::unix::thread` * `RawPthread` * `JoinHandleExt` * `JoinHandleExt::as_pthread_t` * `JoinHandleExt::into_pthread_t` * `HashSet::hasher` * `HashMap::hasher` * `CommandExt::exec` * `File::try_clone` * `SocketAddr::set_ip` * `SocketAddr::set_port` * `SocketAddrV4::set_ip` * `SocketAddrV4::set_port` * `SocketAddrV6::set_ip` * `SocketAddrV6::set_port` * `SocketAddrV6::set_flowinfo` * `SocketAddrV6::set_scope_id` * `<[T]>::copy_from_slice` * `ptr::read_volatile` * `ptr::write_volatile` * The `#[deprecated]` attribute * `OpenOptions::create_new` Deprecated * `std::raw::Slice` - use raw parts of `slice` module instead * `std::raw::Repr` - use raw parts of `slice` module instead * `str::char_range_at` - use slicing plus `chars()` plus `len_utf8` * `str::char_range_at_reverse` - use slicing plus `chars().rev()` plus `len_utf8` * `str::char_at` - use slicing plus `chars()` * `str::char_at_reverse` - use slicing plus `chars().rev()` * `str::slice_shift_char` - use `chars()` plus `Chars::as_str` * `CommandExt::session_leader` - use `before_exec` instead. Closes rust-lang#27719 cc rust-lang#27751 (deprecating the `Slice` bits) Closes rust-lang#27754 Closes rust-lang#27780 Closes rust-lang#27809 Closes rust-lang#27811 Closes rust-lang#27830 Closes rust-lang#28050 Closes rust-lang#29453 Closes rust-lang#29791 Closes rust-lang#29935 Closes rust-lang#30014 Closes rust-lang#30752 Closes rust-lang#31262 cc rust-lang#31398 (still need to deal with `before_exec`) Closes rust-lang#31405 Closes rust-lang#31572 Closes rust-lang#31755 Closes rust-lang#31756
std: Stabilize APIs for the 1.9 release This commit applies all stabilizations, renamings, and deprecations that the library team has decided on for the upcoming 1.9 release. All tracking issues have gone through a cycle-long "final comment period" and the specific APIs stabilized/deprecated are: Stable * `std::panic` * `std::panic::catch_unwind` (renamed from `recover`) * `std::panic::resume_unwind` (renamed from `propagate`) * `std::panic::AssertUnwindSafe` (renamed from `AssertRecoverSafe`) * `std::panic::UnwindSafe` (renamed from `RecoverSafe`) * `str::is_char_boundary` * `<*const T>::as_ref` * `<*mut T>::as_ref` * `<*mut T>::as_mut` * `AsciiExt::make_ascii_uppercase` * `AsciiExt::make_ascii_lowercase` * `char::decode_utf16` * `char::DecodeUtf16` * `char::DecodeUtf16Error` * `char::DecodeUtf16Error::unpaired_surrogate` * `BTreeSet::take` * `BTreeSet::replace` * `BTreeSet::get` * `HashSet::take` * `HashSet::replace` * `HashSet::get` * `OsString::with_capacity` * `OsString::clear` * `OsString::capacity` * `OsString::reserve` * `OsString::reserve_exact` * `OsStr::is_empty` * `OsStr::len` * `std::os::unix::thread` * `RawPthread` * `JoinHandleExt` * `JoinHandleExt::as_pthread_t` * `JoinHandleExt::into_pthread_t` * `HashSet::hasher` * `HashMap::hasher` * `CommandExt::exec` * `File::try_clone` * `SocketAddr::set_ip` * `SocketAddr::set_port` * `SocketAddrV4::set_ip` * `SocketAddrV4::set_port` * `SocketAddrV6::set_ip` * `SocketAddrV6::set_port` * `SocketAddrV6::set_flowinfo` * `SocketAddrV6::set_scope_id` * `<[T]>::copy_from_slice` * `ptr::read_volatile` * `ptr::write_volatile` * The `#[deprecated]` attribute * `OpenOptions::create_new` Deprecated * `std::raw::Slice` - use raw parts of `slice` module instead * `std::raw::Repr` - use raw parts of `slice` module instead * `str::char_range_at` - use slicing plus `chars()` plus `len_utf8` * `str::char_range_at_reverse` - use slicing plus `chars().rev()` plus `len_utf8` * `str::char_at` - use slicing plus `chars()` * `str::char_at_reverse` - use slicing plus `chars().rev()` * `str::slice_shift_char` - use `chars()` plus `Chars::as_str` * `CommandExt::session_leader` - use `before_exec` instead. Closes #27719 cc #27751 (deprecating the `Slice` bits) Closes #27754 Closes #27780 Closes #27809 Closes #27811 Closes #27830 Closes #28050 Closes #29453 Closes #29791 Closes #29935 Closes #30014 Closes #30752 Closes #31262 cc #31398 (still need to deal with `before_exec`) Closes #31405 Closes #31572 Closes #31755 Closes #31756
This commit applies all stabilizations, renamings, and deprecations that the library team has decided on for the upcoming 1.9 release. All tracking issues have gone through a cycle-long "final comment period" and the specific APIs stabilized/deprecated are: Stable * `std::panic` * `std::panic::catch_unwind` (renamed from `recover`) * `std::panic::resume_unwind` (renamed from `propagate`) * `std::panic::AssertUnwindSafe` (renamed from `AssertRecoverSafe`) * `std::panic::UnwindSafe` (renamed from `RecoverSafe`) * `str::is_char_boundary` * `<*const T>::as_ref` * `<*mut T>::as_ref` * `<*mut T>::as_mut` * `AsciiExt::make_ascii_uppercase` * `AsciiExt::make_ascii_lowercase` * `char::decode_utf16` * `char::DecodeUtf16` * `char::DecodeUtf16Error` * `char::DecodeUtf16Error::unpaired_surrogate` * `BTreeSet::take` * `BTreeSet::replace` * `BTreeSet::get` * `HashSet::take` * `HashSet::replace` * `HashSet::get` * `OsString::with_capacity` * `OsString::clear` * `OsString::capacity` * `OsString::reserve` * `OsString::reserve_exact` * `OsStr::is_empty` * `OsStr::len` * `std::os::unix::thread` * `RawPthread` * `JoinHandleExt` * `JoinHandleExt::as_pthread_t` * `JoinHandleExt::into_pthread_t` * `HashSet::hasher` * `HashMap::hasher` * `CommandExt::exec` * `File::try_clone` * `SocketAddr::set_ip` * `SocketAddr::set_port` * `SocketAddrV4::set_ip` * `SocketAddrV4::set_port` * `SocketAddrV6::set_ip` * `SocketAddrV6::set_port` * `SocketAddrV6::set_flowinfo` * `SocketAddrV6::set_scope_id` * `<[T]>::copy_from_slice` * `ptr::read_volatile` * `ptr::write_volatile` * The `#[deprecated]` attribute * `OpenOptions::create_new` Deprecated * `std::raw::Slice` - use raw parts of `slice` module instead * `std::raw::Repr` - use raw parts of `slice` module instead * `str::char_range_at` - use slicing plus `chars()` plus `len_utf8` * `str::char_range_at_reverse` - use slicing plus `chars().rev()` plus `len_utf8` * `str::char_at` - use slicing plus `chars()` * `str::char_at_reverse` - use slicing plus `chars().rev()` * `str::slice_shift_char` - use `chars()` plus `Chars::as_str` * `CommandExt::session_leader` - use `before_exec` instead. Closes rust-lang#27719 cc rust-lang#27751 (deprecating the `Slice` bits) Closes rust-lang#27754 Closes rust-lang#27780 Closes rust-lang#27809 Closes rust-lang#27811 Closes rust-lang#27830 Closes rust-lang#28050 Closes rust-lang#29453 Closes rust-lang#29791 Closes rust-lang#29935 Closes rust-lang#30014 Closes rust-lang#30752 Closes rust-lang#31262 cc rust-lang#31398 (still need to deal with `before_exec`) Closes rust-lang#31405 Closes rust-lang#31572 Closes rust-lang#31755 Closes rust-lang#31756
This is a tracking issue for the unstable
ptr_as_ref
feature of the standard library. These functions allow unsafely converting raw pointers to optional safe references, returningNone
if they're null.I would personally vote for removing these, but there's certainly some usage throughout the standard distribution.
cc @gankro
The text was updated successfully, but these errors were encountered: