[PATCH v2 2/6] rust: types: avoid `as` casts

Tamir Duberstein posted 6 patches 2 weeks, 5 days ago
There is a newer version of this series
[PATCH v2 2/6] rust: types: avoid `as` casts
Posted by Tamir Duberstein 2 weeks, 5 days ago
Replace `as` casts with `cast{,_const,_mut}` which are a bit safer.

Signed-off-by: Tamir Duberstein <tamird@gmail.com>
---
 rust/kernel/alloc/kbox.rs | 10 ++++++----
 rust/kernel/sync/arc.rs   |  9 +++++----
 rust/kernel/types.rs      |  2 +-
 3 files changed, 12 insertions(+), 9 deletions(-)

diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index d69c32496b86a2315f81cafc8e6771ebb0cf10d1..b6b6723098b6b30743bf38c97aab0e701a5a1be4 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -356,13 +356,13 @@ impl<T: 'static, A> ForeignOwnable for Box<T, A>
     type Borrowed<'a> = &'a T;
 
     fn into_foreign(self) -> *const core::ffi::c_void {
-        Box::into_raw(self) as _
+        Box::into_raw(self).cast_const().cast()
     }
 
     unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self {
         // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
         // call to `Self::into_foreign`.
-        unsafe { Box::from_raw(ptr as _) }
+        unsafe { Box::from_raw(ptr.cast_mut().cast()) }
     }
 
     unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> &'a T {
@@ -380,13 +380,15 @@ impl<T: 'static, A> ForeignOwnable for Pin<Box<T, A>>
 
     fn into_foreign(self) -> *const core::ffi::c_void {
         // SAFETY: We are still treating the box as pinned.
-        Box::into_raw(unsafe { Pin::into_inner_unchecked(self) }) as _
+        Box::into_raw(unsafe { Pin::into_inner_unchecked(self) })
+            .cast_const()
+            .cast()
     }
 
     unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self {
         // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
         // call to `Self::into_foreign`.
-        unsafe { Pin::new_unchecked(Box::from_raw(ptr as _)) }
+        unsafe { Pin::new_unchecked(Box::from_raw(ptr.cast_mut().cast())) }
     }
 
     unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> Pin<&'a T> {
diff --git a/rust/kernel/sync/arc.rs b/rust/kernel/sync/arc.rs
index 2c9b7d4a2554278ce8608f4f4c7f9cfe87b21492..af383bcd003e1122ebe1b62a49fe40279458e379 100644
--- a/rust/kernel/sync/arc.rs
+++ b/rust/kernel/sync/arc.rs
@@ -201,10 +201,11 @@ pub fn new(contents: T, flags: Flags) -> Result<Self, AllocError> {
         };
 
         let inner = KBox::new(value, flags)?;
+        let inner = KBox::leak(inner).into();
 
         // SAFETY: We just created `inner` with a reference count of 1, which is owned by the new
         // `Arc` object.
-        Ok(unsafe { Self::from_inner(KBox::leak(inner).into()) })
+        Ok(unsafe { Self::from_inner(inner) })
     }
 }
 
@@ -333,13 +334,13 @@ impl<T: 'static> ForeignOwnable for Arc<T> {
     type Borrowed<'a> = ArcBorrow<'a, T>;
 
     fn into_foreign(self) -> *const core::ffi::c_void {
-        ManuallyDrop::new(self).ptr.as_ptr() as _
+        ManuallyDrop::new(self).ptr.as_ptr().cast_const().cast()
     }
 
     unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> ArcBorrow<'a, T> {
         // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
         // call to `Self::into_foreign`.
-        let inner = unsafe { NonNull::new_unchecked(ptr as *mut ArcInner<T>) };
+        let inner = unsafe { NonNull::new_unchecked(ptr.cast_mut().cast::<ArcInner<T>>()) };
 
         // SAFETY: The safety requirements of `from_foreign` ensure that the object remains alive
         // for the lifetime of the returned value.
@@ -349,7 +350,7 @@ unsafe fn borrow<'a>(ptr: *const core::ffi::c_void) -> ArcBorrow<'a, T> {
     unsafe fn from_foreign(ptr: *const core::ffi::c_void) -> Self {
         // SAFETY: The safety requirements of this function ensure that `ptr` comes from a previous
         // call to `Self::into_foreign`.
-        let inner = unsafe { NonNull::new_unchecked(ptr as *mut ArcInner<T>) };
+        let inner = unsafe { NonNull::new_unchecked(ptr.cast_mut().cast::<ArcInner<T>>()) };
 
         // SAFETY: By the safety requirement of this function, we know that `ptr` came from
         // a previous call to `Arc::into_foreign`, which guarantees that `ptr` is valid and
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index fae80814fa1c5e0f11933f2f15e173f0e3a10fe0..364dd2dc438eb7d1c4d0a4525bf2305a42297b2b 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -418,7 +418,7 @@ pub unsafe fn from_raw(ptr: NonNull<T>) -> Self {
     /// }
     ///
     /// let mut data = Empty {};
-    /// let ptr = NonNull::<Empty>::new(&mut data as *mut _).unwrap();
+    /// let ptr = NonNull::<Empty>::new(&mut data).unwrap();
     /// # // SAFETY: TODO.
     /// let data_ref: ARef<Empty> = unsafe { ARef::from_raw(ptr) };
     /// let raw_ptr: NonNull<Empty> = ARef::into_raw(data_ref);

-- 
2.47.0
Re: [PATCH v2 2/6] rust: types: avoid `as` casts
Posted by Miguel Ojeda 2 weeks, 2 days ago
On Mon, Nov 4, 2024 at 10:20 PM Tamir Duberstein <tamird@gmail.com> wrote:
>
> -    /// let ptr = NonNull::<Empty>::new(&mut data as *mut _).unwrap();
> +    /// let ptr = NonNull::<Empty>::new(&mut data).unwrap();

Nit: this one does not change it to `cast_*()`.

Cheers,
Miguel
Re: [PATCH v2 2/6] rust: types: avoid `as` casts
Posted by Tamir Duberstein 2 weeks, 2 days ago
On Fri, Nov 8, 2024 at 8:13 AM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> On Mon, Nov 4, 2024 at 10:20 PM Tamir Duberstein <tamird@gmail.com> wrote:
> >
> > -    /// let ptr = NonNull::<Empty>::new(&mut data as *mut _).unwrap();
> > +    /// let ptr = NonNull::<Empty>::new(&mut data).unwrap();
>
> Nit: this one does not change it to `cast_*()`.

Ack, will mention this in the commit message.
Re: [PATCH v2 2/6] rust: types: avoid `as` casts
Posted by Alice Ryhl 2 weeks, 2 days ago
On Mon, Nov 4, 2024 at 10:20 PM Tamir Duberstein <tamird@gmail.com> wrote:
>
> Replace `as` casts with `cast{,_const,_mut}` which are a bit safer.
>
> Signed-off-by: Tamir Duberstein <tamird@gmail.com>

The compiler auto-converts from *mut to *const, so only cast_mut() is
necessary. I think this will still compile if you get rid of all of
the cast_const() calls.

Alice
Re: [PATCH v2 2/6] rust: types: avoid `as` casts
Posted by Miguel Ojeda 2 weeks, 2 days ago
On Fri, Nov 8, 2024 at 12:35 PM Alice Ryhl <aliceryhl@google.com> wrote:
>
> The compiler auto-converts from *mut to *const, so only cast_mut() is
> necessary. I think this will still compile if you get rid of all of
> the cast_const() calls.

Yeah, if there was a mode/lint that forced us to avoid the coercion,
then I guess this could eventually make sense as a more explicit (and
symmetric) style around raw pointers  -- I opened:

    https://github.com/rust-lang/rust-clippy/issues/13667

to see what others think.

Cheers,
Miguel
Re: [PATCH v2 2/6] rust: types: avoid `as` casts
Posted by Tamir Duberstein 2 weeks, 2 days ago
On Fri, Nov 8, 2024 at 6:35 AM Alice Ryhl <aliceryhl@google.com> wrote:
>
> On Mon, Nov 4, 2024 at 10:20 PM Tamir Duberstein <tamird@gmail.com> wrote:
> >
> > Replace `as` casts with `cast{,_const,_mut}` which are a bit safer.
> >
> > Signed-off-by: Tamir Duberstein <tamird@gmail.com>
>
> The compiler auto-converts from *mut to *const, so only cast_mut() is
> necessary. I think this will still compile if you get rid of all of
> the cast_const() calls.

I thought that wouldn't work because of type inference but it does - I
guess the compiler derefs *mut T to *const T before the cast() to
*const U.

Will change in v3, thanks.
Re: [PATCH v2 2/6] rust: types: avoid `as` casts
Posted by Miguel Ojeda 2 weeks, 2 days ago
On Fri, Nov 8, 2024 at 1:22 PM Tamir Duberstein <tamird@gmail.com> wrote:
>
> guess the compiler derefs *mut T to *const T before the cast() to

I guess you mean "coerces"? i.e. there shouldn't be a deref, no?

Cheers,
Miguel
Re: [PATCH v2 2/6] rust: types: avoid `as` casts
Posted by Tamir Duberstein 2 weeks, 2 days ago
On Fri, Nov 8, 2024 at 8:15 AM Miguel Ojeda
<miguel.ojeda.sandonis@gmail.com> wrote:
>
> On Fri, Nov 8, 2024 at 1:22 PM Tamir Duberstein <tamird@gmail.com> wrote:
> >
> > guess the compiler derefs *mut T to *const T before the cast() to
>
> I guess you mean "coerces"? i.e. there shouldn't be a deref, no?

I was using "deref" in "deref coercion" sense:

https://doc.rust-lang.org/std/ops/trait.Deref.html#deref-coercion

But it seems that what's really going on is indeed automatic coercion
before the cast() call.