diff --git a/tokio/src/util/linked_list.rs b/tokio/src/util/linked_list.rs index 0ed2b616456..d3b97c54749 100644 --- a/tokio/src/util/linked_list.rs +++ b/tokio/src/util/linked_list.rs @@ -68,6 +68,7 @@ pub(crate) unsafe trait Link { } /// Previous / next pointers. +#[repr(transparent)] pub(crate) struct Pointers { inner: UnsafeCell>, } @@ -78,15 +79,14 @@ pub(crate) struct Pointers { /// Additionally, we never access the `prev` or `next` fields directly, as any /// such access would implicitly involve the creation of a reference to the /// field, which we want to avoid since the fields are not `!Unpin`, and would -/// hence be given the `noalias` attribute if we were to do such an access. -/// As an alternative to accessing the fields directly, the `Pointers` type +/// hence be given the `noalias` attribute if we were to do such an access. As +/// an alternative to accessing the fields directly, the `Pointers` type /// provides getters and setters for the two fields, and those are implemented -/// using raw pointer casts and offsets, which is valid since the struct is -/// #[repr(C)]. +/// using `ptr`-specific methods which avoids the creation of intermediate +/// references. /// /// See this link for more information: /// -#[repr(C)] struct PointersInner { /// The previous node in the list. null if there is no previous node. /// @@ -418,38 +418,28 @@ impl Pointers { } pub(crate) fn get_prev(&self) -> Option> { - // SAFETY: prev is the first field in PointersInner, which is #[repr(C)]. + // SAFETY: Field is accessed immutably from a reference. unsafe { - let inner = self.inner.get(); - let prev = inner as *const Option>; - ptr::read(prev) + ptr::addr_of!((*self.inner.get()).prev).read() } } pub(crate) fn get_next(&self) -> Option> { - // SAFETY: next is the second field in PointersInner, which is #[repr(C)]. + // SAFETY: Field is accessed immutably from a reference. unsafe { - let inner = self.inner.get(); - let prev = inner as *const Option>; - let next = prev.add(1); - ptr::read(next) + ptr::addr_of!((*self.inner.get()).next).read() } } fn set_prev(&mut self, value: Option>) { - // SAFETY: prev is the first field in PointersInner, which is #[repr(C)]. + // SAFETY: Field is accessed mutably from a mutable reference. unsafe { - let inner = self.inner.get(); - let prev = inner as *mut Option>; - ptr::write(prev, value); + ptr::addr_of_mut!((*self.inner.get()).prev).write(value); } } fn set_next(&mut self, value: Option>) { - // SAFETY: next is the second field in PointersInner, which is #[repr(C)]. + // SAFETY: Field is accessed mutably from a mutable reference. unsafe { - let inner = self.inner.get(); - let prev = inner as *mut Option>; - let next = prev.add(1); - ptr::write(next, value); + ptr::addr_of_mut!((*self.inner.get()).next).write(value); } } }