-
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 [*const T|*mut T]::with_metadata_of #75091
Comments
…fJung Requested changes to [*mut T|*const T]::set_ptr_value This is a follow-up to PR rust-lang#74774 (tracking issue rust-lang#75091), acting on some change requests made after approval: - adds `#[must_use]` attribute - changes type of `val` pointer argument from `()` to `u8` - adjusts documentation mentioning pointer provenance
As discussed on Zulip this could be replaced with |
Refactor set_ptr_value as with_metadata_of Replaces `set_ptr_value` (rust-lang#75091) with methods of reversed argument order: ```rust impl<T: ?Sized> *mut T { pub fn with_metadata_of<U: ?Sized>(self, val: *mut U) -> *mut U; } impl<T: ?Sized> *const T { pub fn with_metadata_of<U: ?Sized>(self, val: *const U) -> *const U; } ``` By reversing the arguments we achieve several clarifications: - The function closely resembles `cast` with an argument to initialize the metadata. This is easier to teach and answers a long outstanding question that had restricted cast to `Sized` pointee targets. See multiples reviews of <rust-lang#47631> - The 'object identity', in the form of provenance, is now preserved from the receiver argument to the result. This helps explain the method as a builder-style, instead of some kind of setter that would modify something in-place. Ensuring that the result has the identity of the `self` argument is also beneficial for an intuition of effects. - An outstanding concern, 'Correct argument type', is avoided by not committing to any specific argument type. This is consistent with cast which does not require its receiver to be a 'raw address'. Hopefully the usage examples in `sync/rc.rs` serve as sufficient examples of the style to convince the reader of the readability improvements of this style, when compared to the previous order of arguments. I want to take the opportunity to motivate inclusion of this method _separate_ from metadata API, separate from `feature(ptr_metadata)`. It does _not_ involve the `Pointee` trait in any form. This may be regarded as a very, very light form that does not commit to any details of the pointee trait, or its associated metadata. There are several use cases for which this is already sufficient and no further inspection of metadata is necessary. - Storing the coercion of `*mut T` into `*mut dyn Trait` as a way to dynamically cast some an arbitrary instance of the same type to a dyn trait instance. In particular, one can have a field of type `Option<*mut dyn io::Seek>` to memorize if a particular writer is seekable. Then a method `fn(self: &T) -> Option<&dyn Seek>` can be provided, which does _not_ involve the static trait bound `T: Seek`. This makes it possible to create an API that is capable of utilizing seekable streams and non-seekable streams (instead of a possible less efficient manner such as more buffering) through the same entry-point. - Enabling more generic forms of unsizing for no-`std` smart pointers. Using the stable APIs only few concrete cases are available. One can unsize arrays to `[T]` by `ptr::slice_from_raw_parts` but unsizing a custom smart pointer to, e.g., `dyn Iterator`, `dyn Future`, `dyn Debug`, can't easily be done generically. Exposing `with_metadata_of` would allow smart pointers to offer their own `unsafe` escape hatch with similar parameters where the caller provides the unsized metadata. This is particularly interesting for embedded where `dyn`-trait usage can drastically reduce code size.
Even if we want to keep these methods I think it's better to write them in terms of the metadata API as it's easy to reason about and less error prone than the current implementation. |
The method takes two pointer arguments: one `self` supplying the pointer value, and a second pointer supplying the metadata. The new parameter type more clearly reflects the actual requirements. The provenance of the metadata parameter is disregarded completely. Using a mutable pointer in the call site can be coerced to a const pointer while the reverse is not true. An example of the current use: ```rust // Manually taking an unsized object from a `ManuallyDrop` into another allocation. let val: &core::mem::ManuallyDrop<T> = …; let ptr = val as *const _ as *mut T; let ptr = uninit.as_ptr().with_metadata_of(ptr); ``` This could then instead be simplified to: ```rust // Manually taking an unsized object from a `ManuallyDrop` into another allocation. let val: &core::mem::ManuallyDrop<T> = …; let ptr = uninit.as_ptr().with_metadata_of(&**val); ```
…nter_argument, r=dtolnay Adjust argument type for mutable with_metadata_of (rust-lang#75091) The method takes two pointer arguments: one `self` supplying the pointer value, and a second pointer supplying the metadata. The new parameter type more clearly reflects the actual requirements. The provenance of the metadata parameter is disregarded completely. Using a mutable pointer in the call site can be coerced to a const pointer while the reverse is not true. In some cases, the current parameter type can thus lead to a very slightly confusing additional cast. [Example](HeroicKatora/static-alloc@cad9377). ```rust // Manually taking an unsized object from a `ManuallyDrop` into another allocation. let val: &core::mem::ManuallyDrop<T> = …; let ptr = val as *const _ as *mut T; let ptr = uninit.as_ptr().with_metadata_of(ptr); ``` This could then instead be simplified to: ```rust // Manually taking an unsized object from a `ManuallyDrop` into another allocation. let val: &core::mem::ManuallyDrop<T> = …; let ptr = uninit.as_ptr().with_metadata_of(&**val); ``` Tracking issue: rust-lang#75091 `@dtolnay` you're reviewed rust-lang#95249, would you mind chiming in?
…nter_argument, r=dtolnay Adjust argument type for mutable with_metadata_of (rust-lang#75091) The method takes two pointer arguments: one `self` supplying the pointer value, and a second pointer supplying the metadata. The new parameter type more clearly reflects the actual requirements. The provenance of the metadata parameter is disregarded completely. Using a mutable pointer in the call site can be coerced to a const pointer while the reverse is not true. In some cases, the current parameter type can thus lead to a very slightly confusing additional cast. [Example](HeroicKatora/static-alloc@cad9377). ```rust // Manually taking an unsized object from a `ManuallyDrop` into another allocation. let val: &core::mem::ManuallyDrop<T> = …; let ptr = val as *const _ as *mut T; let ptr = uninit.as_ptr().with_metadata_of(ptr); ``` This could then instead be simplified to: ```rust // Manually taking an unsized object from a `ManuallyDrop` into another allocation. let val: &core::mem::ManuallyDrop<T> = …; let ptr = uninit.as_ptr().with_metadata_of(&**val); ``` Tracking issue: rust-lang#75091 ``@dtolnay`` you're reviewed rust-lang#95249, would you mind chiming in?
Rollup of 7 pull requests Successful merges: - rust-lang#102602 (Slightly tweak comments wrt `lint_overflowing_range_endpoint`) - rust-lang#103190 (rustdoc: render bounds of cross-crate GAT params) - rust-lang#103224 (Allow semicolon after closure within parentheses in macros) - rust-lang#103280 ((rust-lang#102929) Implement `String::leak` (attempt 2)) - rust-lang#103329 (Add a forgotten check for NonNull::new_unchecked's precondition) - rust-lang#103346 (Adjust argument type for mutable with_metadata_of (rust-lang#75091)) - rust-lang#103360 (Reduce false positives in msys2 detection) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
…ation__--this-can-be-simplified, r=scottmcm Simplify some pointer method implementations - Make `pointer::with_metadata_of` const (+simplify implementation) (cc rust-lang#75091) - Simplify implementation of various pointer methods r? `@scottmcm` ---- `from_raw_parts::<T>(this, metadata(self))` was annoying me for a while and I've finally figured out how it should _actually_ be done.
…ation__--this-can-be-simplified, r=scottmcm Simplify some pointer method implementations - Make `pointer::with_metadata_of` const (+simplify implementation) (cc rust-lang#75091) - Simplify implementation of various pointer methods r? ``@scottmcm`` ---- `from_raw_parts::<T>(this, metadata(self))` was annoying me for a while and I've finally figured out how it should _actually_ be done.
…ation__--this-can-be-simplified, r=scottmcm Simplify some pointer method implementations - Make `pointer::with_metadata_of` const (+simplify implementation) (cc rust-lang#75091) - Simplify implementation of various pointer methods r? ```@scottmcm``` ---- `from_raw_parts::<T>(this, metadata(self))` was annoying me for a while and I've finally figured out how it should _actually_ be done.
…ment, r=dtolnay Adjust argument type for mutable with_metadata_of (#75091) The method takes two pointer arguments: one `self` supplying the pointer value, and a second pointer supplying the metadata. The new parameter type more clearly reflects the actual requirements. The provenance of the metadata parameter is disregarded completely. Using a mutable pointer in the call site can be coerced to a const pointer while the reverse is not true. In some cases, the current parameter type can thus lead to a very slightly confusing additional cast. [Example](HeroicKatora/static-alloc@cad9377). ```rust // Manually taking an unsized object from a `ManuallyDrop` into another allocation. let val: &core::mem::ManuallyDrop<T> = …; let ptr = val as *const _ as *mut T; let ptr = uninit.as_ptr().with_metadata_of(ptr); ``` This could then instead be simplified to: ```rust // Manually taking an unsized object from a `ManuallyDrop` into another allocation. let val: &core::mem::ManuallyDrop<T> = …; let ptr = uninit.as_ptr().with_metadata_of(&**val); ``` Tracking issue: rust-lang/rust#75091 ``@dtolnay`` you're reviewed #95249, would you mind chiming in?
This needs a better motivational example. From current docs:
This is superceeded by |
|
|
This comment was marked as off-topic.
This comment was marked as off-topic.
That will use the provenance of |
For the "Is this even needed/useful given that there now also is #81513?", I feel like this is super useful even with or without the metadata APIs.
I'd love to see this stabilized, if that is a good resolution to the last question needed answering. |
@rust-lang/libs-api see above |
Hmm, I think the primary alternative to this would be something like rust-lang/libs-team#246 -- instead of copying the metadata from a full other pointer, just remove the blocker to letting you pass around the metadata directly. It's not obvious to me that people really ever want this version where you need to pass a full pointer, just to ignore its address. Or is there some situation I'm not thinking of where that's really better than doing a |
As I said above @scottmcm:
My motivating example is https://github.com/andylokandy/smallbox which has been assuming fat pointer layout for years and I recently added a nightly feature which uses this API and strict provenance. Since strict provenance is in the process of being stabilized, this being stabilized as well would be amazing for |
This comment has been minimized.
This comment has been minimized.
@HeroicKatora IMO it makes little sense to have a function This tracking issue is specifically about copying the metadata from one pointer to another. Your proposal would be part of #81513. |
I understood @scottmcm as a new question, separate from #81513 itself, to explore whether rust-lang/libs-team#246 changes something about the unresolved redundancy question in the issue. It is not accepted, so not yet a part of #81513 to my understanding (and not linked there either). Maybe I'm misreading the process here. Neither the API of this (#75091) nor the sketch based on rust-lang/libs-team#246 would require stabilization of the Are you suggesting the redundancy even with the ACP is slight enough that it would still not be problematic, and there's enough merit to consuming a pointer directly? Definitely a reasonable position to take. I just intended for it to be clarified that the ACP presents a (middle ground) alternative not yet explored in comments in this thread. If libs is in favor of potentially having both that's fine 👍 |
All I am saying is, we should not have functions called This issue here is specifically about the two-pointer version of the APIs, which avoids stabilizing any new type. IOW, rust-lang/libs-team#246 is a modification of #81513, but has absolutely no bearing on this issue. |
…tation, r=Mark-Simulacrum Expand set_ptr_value / with_metadata_of docs In preparation of a potential FCP, intends to clean up and expand the documentation of this operation. Rewrite these blobs to explicitly mention the case of a sized operand. The previous made that seem wrong instead of emphasizing it is nothing but a simple cast. Instead, the explanation now emphasizes that the address portion of the argument, together with its provenance, is discarded which previously had to be inferred by the reader. Then an example demonstrates a simple line of incorrect usage based on this idea of provenance. Tracking issue: rust-lang#75091
…tation, r=Mark-Simulacrum Expand set_ptr_value / with_metadata_of docs In preparation of a potential FCP, intends to clean up and expand the documentation of this operation. Rewrite these blobs to explicitly mention the case of a sized operand. The previous made that seem wrong instead of emphasizing it is nothing but a simple cast. Instead, the explanation now emphasizes that the address portion of the argument, together with its provenance, is discarded which previously had to be inferred by the reader. Then an example demonstrates a simple line of incorrect usage based on this idea of provenance. Tracking issue: rust-lang#75091
Rollup merge of rust-lang#131339 - HeroicKatora:set_ptr_value-documentation, r=Mark-Simulacrum Expand set_ptr_value / with_metadata_of docs In preparation of a potential FCP, intends to clean up and expand the documentation of this operation. Rewrite these blobs to explicitly mention the case of a sized operand. The previous made that seem wrong instead of emphasizing it is nothing but a simple cast. Instead, the explanation now emphasizes that the address portion of the argument, together with its provenance, is discarded which previously had to be inferred by the reader. Then an example demonstrates a simple line of incorrect usage based on this idea of provenance. Tracking issue: rust-lang#75091
…=Mark-Simulacrum Expand set_ptr_value / with_metadata_of docs In preparation of a potential FCP, intends to clean up and expand the documentation of this operation. Rewrite these blobs to explicitly mention the case of a sized operand. The previous made that seem wrong instead of emphasizing it is nothing but a simple cast. Instead, the explanation now emphasizes that the address portion of the argument, together with its provenance, is discarded which previously had to be inferred by the reader. Then an example demonstrates a simple line of incorrect usage based on this idea of provenance. Tracking issue: rust-lang/rust#75091
Feature gate:
#![feature(set_ptr_value)]
Public API
Steps / History
#[must_use]
: Requested changes to [*mut T|*const T]::set_ptr_value #75407with_metadata_of
: Refactor set_ptr_value as with_metadata_of #95249Unresolved Questions
*mut ()
?*mut u8
?*mut Opaque
?The text was updated successfully, but these errors were encountered: