add associated Payload type to ArenaAllocated

This commit is contained in:
Bennet Bleßmann
2024-07-06 15:37:08 +02:00
parent d87400afa0
commit 285f11ccdc
5 changed files with 131 additions and 81 deletions

View File

@@ -5,7 +5,6 @@ use crate::http::{HttpListener, HttpResponse};
use crate::machine::loader::LiveLoadState; use crate::machine::loader::LiveLoadState;
use crate::machine::machine_indices::*; use crate::machine::machine_indices::*;
use crate::machine::streams::*; use crate::machine::streams::*;
use crate::parser::char_reader::CharReader;
use crate::raw_block::*; use crate::raw_block::*;
use crate::read::*; use crate::read::*;
use crate::types::UntypedArenaPtr; use crate::types::UntypedArenaPtr;
@@ -45,9 +44,12 @@ macro_rules! float_alloc {
}}; }};
} }
pub fn header_offset_from_payload<Payload: Sized>() -> usize { pub fn header_offset_from_payload<T: ?Sized + ArenaAllocated>() -> usize
let payload_offset = mem::offset_of!(TypedAllocSlab<Payload>, payload); where
let slab_offset = mem::offset_of!(TypedAllocSlab<Payload>, slab); T::Payload: Sized,
{
let payload_offset = mem::offset_of!(TypedAllocSlab<T>, payload);
let slab_offset = mem::offset_of!(TypedAllocSlab<T>, slab);
let header_offset = slab_offset + mem::offset_of!(AllocSlab, header); let header_offset = slab_offset + mem::offset_of!(AllocSlab, header);
debug_assert!(payload_offset > header_offset); debug_assert!(payload_offset > header_offset);
@@ -220,60 +222,75 @@ impl ArenaHeader {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct TypedArenaPtr<T: ?Sized>(ptr::NonNull<T>); pub struct TypedArenaPtr<T: ?Sized + ArenaAllocated>(ptr::NonNull<T::Payload>);
impl<T: ?Sized + PartialOrd> PartialOrd for TypedArenaPtr<T> { impl<T: ?Sized + ArenaAllocated> PartialOrd for TypedArenaPtr<T>
where
T::Payload: PartialOrd,
{
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
(**self).partial_cmp(&**other) (**self).partial_cmp(&**other)
} }
} }
impl<T: ?Sized + PartialEq> PartialEq for TypedArenaPtr<T> { impl<T: ?Sized + ArenaAllocated> PartialEq for TypedArenaPtr<T>
where
T::Payload: PartialEq,
{
fn eq(&self, other: &TypedArenaPtr<T>) -> bool { fn eq(&self, other: &TypedArenaPtr<T>) -> bool {
std::ptr::addr_eq(self.0.as_ptr(), other.0.as_ptr()) || **self == **other std::ptr::addr_eq(self.0.as_ptr(), other.0.as_ptr()) || **self == **other
} }
} }
impl<T: ?Sized + PartialEq> Eq for TypedArenaPtr<T> {} impl<T: ?Sized + ArenaAllocated> Eq for TypedArenaPtr<T> where T::Payload: Eq {}
impl<T: ?Sized + Ord> Ord for TypedArenaPtr<T> { impl<T: ?Sized + ArenaAllocated> Ord for TypedArenaPtr<T>
where
T::Payload: Ord,
{
fn cmp(&self, other: &Self) -> std::cmp::Ordering { fn cmp(&self, other: &Self) -> std::cmp::Ordering {
(**self).cmp(&**other) (**self).cmp(&**other)
} }
} }
impl<T: ?Sized + Hash> Hash for TypedArenaPtr<T> { impl<T: ?Sized + ArenaAllocated> Hash for TypedArenaPtr<T>
where
T::Payload: Hash,
{
#[inline(always)] #[inline(always)]
fn hash<H: Hasher>(&self, hasher: &mut H) { fn hash<H: Hasher>(&self, hasher: &mut H) {
(self as &T).hash(hasher) (self as &T::Payload).hash(hasher)
} }
} }
impl<T: ?Sized> Clone for TypedArenaPtr<T> { impl<T: ?Sized + ArenaAllocated> Clone for TypedArenaPtr<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
} }
impl<T: ?Sized> Copy for TypedArenaPtr<T> {} impl<T: ?Sized + ArenaAllocated> Copy for TypedArenaPtr<T> {}
impl<T: ?Sized> Deref for TypedArenaPtr<T> { impl<T: ?Sized + ArenaAllocated> Deref for TypedArenaPtr<T> {
type Target = T; type Target = T::Payload;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
unsafe { self.0.as_ref() } unsafe { self.0.as_ref() }
} }
} }
impl<T: ?Sized> DerefMut for TypedArenaPtr<T> { impl<T: ?Sized + ArenaAllocated> DerefMut for TypedArenaPtr<T> {
fn deref_mut(&mut self) -> &mut Self::Target { fn deref_mut(&mut self) -> &mut Self::Target {
unsafe { self.0.as_mut() } unsafe { self.0.as_mut() }
} }
} }
impl<T: fmt::Display> fmt::Display for TypedArenaPtr<T> { impl<T: ArenaAllocated> fmt::Display for TypedArenaPtr<T>
where
T::Payload: fmt::Display,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", **self) write!(f, "{}", (self as &T::Payload))
} }
} }
@@ -282,15 +299,20 @@ impl<T: ?Sized + ArenaAllocated> TypedArenaPtr<T> {
/// - the pointers referee type is correct, safe code depends on the correctness of the type argument /// - the pointers referee type is correct, safe code depends on the correctness of the type argument
/// - the pointer is allocated in the arena /// - the pointer is allocated in the arena
#[inline] #[inline]
pub const unsafe fn new(data: *mut T) -> Self { pub const unsafe fn new(data: *mut T::Payload) -> Self {
unsafe { TypedArenaPtr(ptr::NonNull::new_unchecked(data)) } unsafe { TypedArenaPtr(ptr::NonNull::new_unchecked(data)) }
} }
#[inline] #[inline]
pub fn as_ptr(&self) -> *mut T { pub fn as_ptr(&self) -> *mut T::Payload {
self.0.as_ptr() self.0.as_ptr()
} }
}
impl<T: ?Sized + ArenaAllocated> TypedArenaPtr<T>
where
T::Payload: Sized,
{
#[inline] #[inline]
pub fn header_ptr(&self) -> *const ArenaHeader { pub fn header_ptr(&self) -> *const ArenaHeader {
unsafe { self.as_ptr().byte_sub(T::header_offset_from_payload()) as *const _ } unsafe { self.as_ptr().byte_sub(T::header_offset_from_payload()) as *const _ }
@@ -333,24 +355,35 @@ impl<T: ?Sized + ArenaAllocated> TypedArenaPtr<T> {
} }
} }
pub trait ArenaAllocated: Sized { pub trait ArenaAllocated {
type Payload: ?Sized;
fn tag() -> ArenaHeaderTag; fn tag() -> ArenaHeaderTag;
fn header_offset_from_payload() -> usize { fn header_offset_from_payload() -> usize
where
Self::Payload: Sized,
{
header_offset_from_payload::<Self>() header_offset_from_payload::<Self>()
} }
/// # Safety /// # Safety
/// - the caller must guarantee that the pointee type of UntypedArenaPtr is Self /// - the caller must guarantee that the pointee type of UntypedArenaPtr is Self
unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr<Self> { unsafe fn typed_ptr(ptr: UntypedArenaPtr) -> TypedArenaPtr<Self>
where
Self::Payload: Sized,
{
// safety: // safety:
// - allocated in an arena as from an UntypedArenaPtr // - allocated in an arena as from an UntypedArenaPtr
// - caller guarantees the type is correct // - caller guarantees the type is correct
unsafe { TypedArenaPtr::new(ptr.payload_offset().cast_mut().cast::<Self>()) } unsafe { TypedArenaPtr::new(ptr.payload_offset().cast_mut().cast::<Self::Payload>()) }
} }
#[allow(clippy::missing_safety_doc)] #[allow(clippy::missing_safety_doc)]
fn alloc(arena: &mut Arena, value: Self) -> TypedArenaPtr<Self> { fn alloc(arena: &mut Arena, value: Self::Payload) -> TypedArenaPtr<Self>
where
Self::Payload: Sized,
{
let size = mem::size_of::<TypedAllocSlab<Self>>(); let size = mem::size_of::<TypedAllocSlab<Self>>();
let slab = Box::new(TypedAllocSlab { let slab = Box::new(TypedAllocSlab {
slab: AllocSlab { slab: AllocSlab {
@@ -512,6 +545,7 @@ impl fmt::Display for F64Offset {
} }
impl ArenaAllocated for Integer { impl ArenaAllocated for Integer {
type Payload = Self;
#[inline] #[inline]
fn tag() -> ArenaHeaderTag { fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::Integer ArenaHeaderTag::Integer
@@ -519,6 +553,7 @@ impl ArenaAllocated for Integer {
} }
impl ArenaAllocated for Rational { impl ArenaAllocated for Rational {
type Payload = Self;
#[inline] #[inline]
fn tag() -> ArenaHeaderTag { fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::Rational ArenaHeaderTag::Rational
@@ -526,6 +561,7 @@ impl ArenaAllocated for Rational {
} }
impl ArenaAllocated for LiveLoadState { impl ArenaAllocated for LiveLoadState {
type Payload = Self;
#[inline] #[inline]
fn tag() -> ArenaHeaderTag { fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::LiveLoadState ArenaHeaderTag::LiveLoadState
@@ -533,6 +569,7 @@ impl ArenaAllocated for LiveLoadState {
} }
impl ArenaAllocated for TcpListener { impl ArenaAllocated for TcpListener {
type Payload = Self;
#[inline] #[inline]
fn tag() -> ArenaHeaderTag { fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::TcpListener ArenaHeaderTag::TcpListener
@@ -541,6 +578,7 @@ impl ArenaAllocated for TcpListener {
#[cfg(feature = "http")] #[cfg(feature = "http")]
impl ArenaAllocated for HttpListener { impl ArenaAllocated for HttpListener {
type Payload = Self;
#[inline] #[inline]
fn tag() -> ArenaHeaderTag { fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::HttpListener ArenaHeaderTag::HttpListener
@@ -549,6 +587,7 @@ impl ArenaAllocated for HttpListener {
#[cfg(feature = "http")] #[cfg(feature = "http")]
impl ArenaAllocated for HttpResponse { impl ArenaAllocated for HttpResponse {
type Payload = Self;
#[inline] #[inline]
fn tag() -> ArenaHeaderTag { fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::HttpResponse ArenaHeaderTag::HttpResponse
@@ -556,6 +595,7 @@ impl ArenaAllocated for HttpResponse {
} }
impl ArenaAllocated for IndexPtr { impl ArenaAllocated for IndexPtr {
type Payload = Self;
#[inline] #[inline]
fn tag() -> ArenaHeaderTag { fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::IndexPtrUndefined ArenaHeaderTag::IndexPtrUndefined
@@ -625,16 +665,16 @@ pub struct AllocSlab {
#[repr(C)] #[repr(C)]
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct TypedAllocSlab<Payload> { pub struct TypedAllocSlab<T: ?Sized + ArenaAllocated> {
slab: AllocSlab, slab: AllocSlab,
payload: Payload, payload: T::Payload,
} }
impl<Payload: ArenaAllocated> TypedAllocSlab<Payload> { impl<T: ?Sized + ArenaAllocated> TypedAllocSlab<T> {
/// # Safety /// # Safety
/// - ptr points to a valid allocation of Self /// - ptr points to a valid allocation of Self
#[inline] #[inline]
pub unsafe fn to_typed_arena_ptr(ptr: *mut Self) -> TypedArenaPtr<Payload> { pub unsafe fn to_typed_arena_ptr(ptr: *mut Self) -> TypedArenaPtr<T> {
// safety: // safety:
// - this is the arena allocation of corresponding type // - this is the arena allocation of corresponding type
unsafe { TypedArenaPtr::new(addr_of_mut!((*ptr).payload)) } unsafe { TypedArenaPtr::new(addr_of_mut!((*ptr).payload)) }
@@ -676,34 +716,34 @@ unsafe fn drop_slab_in_place(value: NonNull<AllocSlab>) {
drop_typed_slab_in_place!(Rational, value); drop_typed_slab_in_place!(Rational, value);
} }
ArenaHeaderTag::InputFileStream => { ArenaHeaderTag::InputFileStream => {
drop_typed_slab_in_place!(StreamLayout<CharReader<InputFileStream>>, value); drop_typed_slab_in_place!(InputFileStream, value);
} }
ArenaHeaderTag::OutputFileStream => { ArenaHeaderTag::OutputFileStream => {
drop_typed_slab_in_place!(StreamLayout<OutputFileStream>, value); drop_typed_slab_in_place!(OutputFileStream, value);
} }
ArenaHeaderTag::NamedTcpStream => { ArenaHeaderTag::NamedTcpStream => {
drop_typed_slab_in_place!(StreamLayout<CharReader<NamedTcpStream>>, value); drop_typed_slab_in_place!(NamedTcpStream, value);
} }
ArenaHeaderTag::NamedTlsStream => { ArenaHeaderTag::NamedTlsStream => {
#[cfg(feature = "tls")] #[cfg(feature = "tls")]
drop_typed_slab_in_place!(StreamLayout<CharReader<NamedTlsStream>>, value); drop_typed_slab_in_place!(NamedTlsStream, value);
} }
ArenaHeaderTag::HttpReadStream => { ArenaHeaderTag::HttpReadStream => {
#[cfg(feature = "http")] #[cfg(feature = "http")]
drop_typed_slab_in_place!(StreamLayout<CharReader<HttpReadStream>>, value); drop_typed_slab_in_place!(HttpReadStream, value);
} }
ArenaHeaderTag::HttpWriteStream => { ArenaHeaderTag::HttpWriteStream => {
#[cfg(feature = "http")] #[cfg(feature = "http")]
drop_typed_slab_in_place!(StreamLayout<CharReader<HttpWriteStream>>, value); drop_typed_slab_in_place!(HttpWriteStream, value);
} }
ArenaHeaderTag::ReadlineStream => { ArenaHeaderTag::ReadlineStream => {
drop_typed_slab_in_place!(StreamLayout<ReadlineStream>, value); drop_typed_slab_in_place!(ReadlineStream, value);
} }
ArenaHeaderTag::StaticStringStream => { ArenaHeaderTag::StaticStringStream => {
drop_typed_slab_in_place!(StreamLayout<StaticStringStream>, value); drop_typed_slab_in_place!(StaticStringStream, value);
} }
ArenaHeaderTag::ByteStream => { ArenaHeaderTag::ByteStream => {
drop_typed_slab_in_place!(StreamLayout<CharReader<ByteStream>>, value); drop_typed_slab_in_place!(ByteStream, value);
} }
ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => { ArenaHeaderTag::LiveLoadState | ArenaHeaderTag::InactiveLoadState => {
drop_typed_slab_in_place!(LiveLoadState, value); drop_typed_slab_in_place!(LiveLoadState, value);
@@ -721,10 +761,10 @@ unsafe fn drop_slab_in_place(value: NonNull<AllocSlab>) {
drop_typed_slab_in_place!(HttpResponse, value); drop_typed_slab_in_place!(HttpResponse, value);
} }
ArenaHeaderTag::StandardOutputStream => { ArenaHeaderTag::StandardOutputStream => {
drop_typed_slab_in_place!(StreamLayout<StandardOutputStream>, value); drop_typed_slab_in_place!(StandardOutputStream, value);
} }
ArenaHeaderTag::StandardErrorStream => { ArenaHeaderTag::StandardErrorStream => {
drop_typed_slab_in_place!(StreamLayout<StandardErrorStream>, value); drop_typed_slab_in_place!(StandardErrorStream, value);
} }
ArenaHeaderTag::NullStream ArenaHeaderTag::NullStream
| ArenaHeaderTag::IndexPtrUndefined | ArenaHeaderTag::IndexPtrUndefined

View File

@@ -1757,7 +1757,7 @@ impl Machine {
#[inline] #[inline]
pub(crate) fn push_load_state_payload(&mut self) { pub(crate) fn push_load_state_payload(&mut self) {
let payload = arena_alloc!( let payload: TypedArenaPtr<LiveLoadState> = arena_alloc!(
LoadStatePayload::new(self.code.len(), LiveTermStream::new(ListingSource::User),), LoadStatePayload::new(self.code.len(), LiveTermStream::new(ListingSource::User),),
&mut self.machine_st.arena &mut self.machine_st.arena
); );

View File

@@ -451,7 +451,9 @@ impl<T> DerefMut for StreamLayout<T> {
macro_rules! arena_allocated_impl_for_stream { macro_rules! arena_allocated_impl_for_stream {
($stream_type:ty, $stream_tag:ident) => { ($stream_type:ty, $stream_tag:ident) => {
impl ArenaAllocated for StreamLayout<$stream_type> { impl ArenaAllocated for $stream_tag {
type Payload = StreamLayout<$stream_type>;
#[inline] #[inline]
fn tag() -> ArenaHeaderTag { fn tag() -> ArenaHeaderTag {
ArenaHeaderTag::$stream_tag ArenaHeaderTag::$stream_tag
@@ -477,26 +479,26 @@ arena_allocated_impl_for_stream!(StandardErrorStream, StandardErrorStream);
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub enum Stream { pub enum Stream {
Byte(TypedArenaPtr<StreamLayout<CharReader<ByteStream>>>), Byte(TypedArenaPtr<ByteStream>),
InputFile(TypedArenaPtr<StreamLayout<CharReader<InputFileStream>>>), InputFile(TypedArenaPtr<InputFileStream>),
OutputFile(TypedArenaPtr<StreamLayout<OutputFileStream>>), OutputFile(TypedArenaPtr<OutputFileStream>),
StaticString(TypedArenaPtr<StreamLayout<StaticStringStream>>), StaticString(TypedArenaPtr<StaticStringStream>),
NamedTcp(TypedArenaPtr<StreamLayout<CharReader<NamedTcpStream>>>), NamedTcp(TypedArenaPtr<NamedTcpStream>),
#[cfg(feature = "tls")] #[cfg(feature = "tls")]
NamedTls(TypedArenaPtr<StreamLayout<CharReader<NamedTlsStream>>>), NamedTls(TypedArenaPtr<NamedTlsStream>),
#[cfg(feature = "http")] #[cfg(feature = "http")]
HttpRead(TypedArenaPtr<StreamLayout<CharReader<HttpReadStream>>>), HttpRead(TypedArenaPtr<HttpReadStream>),
#[cfg(feature = "http")] #[cfg(feature = "http")]
HttpWrite(TypedArenaPtr<StreamLayout<CharReader<HttpWriteStream>>>), HttpWrite(TypedArenaPtr<HttpWriteStream>),
Null(StreamOptions), Null(StreamOptions),
Readline(TypedArenaPtr<StreamLayout<ReadlineStream>>), Readline(TypedArenaPtr<ReadlineStream>),
StandardOutput(TypedArenaPtr<StreamLayout<StandardOutputStream>>), StandardOutput(TypedArenaPtr<StandardOutputStream>),
StandardError(TypedArenaPtr<StreamLayout<StandardErrorStream>>), StandardError(TypedArenaPtr<StandardErrorStream>),
} }
impl From<TypedArenaPtr<StreamLayout<ReadlineStream>>> for Stream { impl From<TypedArenaPtr<ReadlineStream>> for Stream {
#[inline] #[inline]
fn from(stream: TypedArenaPtr<StreamLayout<ReadlineStream>>) -> Stream { fn from(stream: TypedArenaPtr<ReadlineStream>) -> Stream {
Stream::Readline(stream) Stream::Readline(stream)
} }
} }

View File

@@ -4519,7 +4519,8 @@ impl Machine {
}); });
let http_listener = HttpListener { incoming: rx }; let http_listener = HttpListener { incoming: rx };
let http_listener = arena_alloc!(http_listener, &mut self.machine_st.arena); let http_listener: TypedArenaPtr<HttpListener> =
arena_alloc!(http_listener, &mut self.machine_st.arena);
let addr = self.deref_register(2); let addr = self.deref_register(2);
self.machine_st.bind( self.machine_st.bind(
@@ -4584,7 +4585,7 @@ impl Machine {
self.indices.streams.insert(stream); self.indices.streams.insert(stream);
let stream = stream_as_cell!(stream); let stream = stream_as_cell!(stream);
let handle = arena_alloc!(request.response, &mut self.machine_st.arena); let handle: TypedArenaPtr<HttpResponse> = arena_alloc!(request.response, &mut self.machine_st.arena);
self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom)); self.machine_st.bind(method.as_var().unwrap(), atom_as_cell!(method_atom));
self.machine_st.bind(path.as_var().unwrap(), path_cell); self.machine_st.bind(path.as_var().unwrap(), path_cell);
@@ -6516,32 +6517,33 @@ impl Machine {
format!("{}:{}", socket_atom.as_str(), port) format!("{}:{}", socket_atom.as_str(), port)
}; };
let (tcp_listener, port) = match TcpListener::bind(server_addr).map_err(|e| e.kind()) { let (tcp_listener, port): (TypedArenaPtr<TcpListener>, _) =
Ok(tcp_listener) => { match TcpListener::bind(server_addr).map_err(|e| e.kind()) {
let port = tcp_listener.local_addr().map(|addr| addr.port()).ok(); Ok(tcp_listener) => {
let port = tcp_listener.local_addr().map(|addr| addr.port()).ok();
if let Some(port) = port { if let Some(port) = port {
( (
arena_alloc!(tcp_listener, &mut self.machine_st.arena), arena_alloc!(tcp_listener, &mut self.machine_st.arena),
port as usize, port as usize,
) )
} else { } else {
self.machine_st.fail = true;
return Ok(());
}
}
Err(ErrorKind::PermissionDenied) => {
return Err(self.machine_st.open_permission_error(
addr,
atom!("socket_server_open"),
2,
));
}
_ => {
self.machine_st.fail = true; self.machine_st.fail = true;
return Ok(()); return Ok(());
} }
} };
Err(ErrorKind::PermissionDenied) => {
return Err(self.machine_st.open_permission_error(
addr,
atom!("socket_server_open"),
2,
));
}
_ => {
self.machine_st.fail = true;
return Ok(());
}
};
let addr = self.deref_register(3); let addr = self.deref_register(3);
self.machine_st.bind( self.machine_st.bind(

View File

@@ -300,7 +300,10 @@ impl fmt::Debug for HeapCellValue {
} }
} }
impl<T: ArenaAllocated> From<TypedArenaPtr<T>> for HeapCellValue { impl<T: ArenaAllocated> From<TypedArenaPtr<T>> for HeapCellValue
where
T::Payload: Sized,
{
#[inline] #[inline]
fn from(arena_ptr: TypedArenaPtr<T>) -> HeapCellValue { fn from(arena_ptr: TypedArenaPtr<T>) -> HeapCellValue {
HeapCellValue::from(arena_ptr.header_ptr() as u64) HeapCellValue::from(arena_ptr.header_ptr() as u64)
@@ -708,7 +711,10 @@ impl UntypedArenaPtr {
/// # Safety /// # Safety
/// - this UntypedArenaPtr actuall pointee type is T /// - this UntypedArenaPtr actuall pointee type is T
#[inline] #[inline]
pub unsafe fn as_typed_ptr<T: ArenaAllocated>(self) -> TypedArenaPtr<T> { pub unsafe fn as_typed_ptr<T: ?Sized + ArenaAllocated>(self) -> TypedArenaPtr<T>
where
T::Payload: Sized,
{
T::typed_ptr(self) T::typed_ptr(self)
} }