Refactor set_ptr_value as with_metadata_of by 197g · Pull Request #95249 · rust-lang/rust (original) (raw)
Replaces set_ptr_value
(#75091) with methods of reversed argument order:
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 toSized
pointee
targets. See multiples reviews of
Add some APIs to ptr::NonNull and fix since attributes #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 theself
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 typeOption<*mut dyn io::Seek>
to memorize if a particular writer is seekable. Then a methodfn(self: &T) -> Option<&dyn Seek>
can be provided, which does not involve the static trait boundT: 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]
byptr::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. Exposingwith_metadata_of
would allow smart pointers to offer their ownunsafe
escape hatch with similar parameters where the caller provides the unsized metadata. This is particularly interesting for embedded wheredyn
-trait usage can drastically reduce code size.