From c1a4e29a1ec2b3a54fa0449ed28bb59ec00ac1ed Mon Sep 17 00:00:00 2001 From: Tristan Guichaoua <33934311+tguichaoua@users.noreply.github.com> Date: Mon, 12 Feb 2024 00:19:36 +0100 Subject: [PATCH] Replace pointer castings (`as`) by their API equivalent (#11818) # Objective Since rust `1.76`, [`ptr::from_ref`](https://doc.rust-lang.org/stable/std/ptr/fn.from_ref.html) and [`ptr::from_mut`](https://doc.rust-lang.org/stable/std/ptr/fn.from_mut.html) are stable. This PR replaces code that use `as` casting by one of `ptr::from_ref`, `ptr::from_mut`, `cast_mut`, `cast_const`, or `cast` methods, which are less error-prone. ## Solution - Bump MSRV to `1.76.0` - Enables the following clippy lints: - [`ptr_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#/ptr_as_ptr) - [`ptr_cast_constness`](https://rust-lang.github.io/rust-clippy/master/index.html#/ptr_cast_constness) - [`ref_as_ptr`](https://rust-lang.github.io/rust-clippy/master/index.html#/ref_as_ptr) (I fix all warnings for this one, but it requires rust 1.77 to be enabled) - Fix the lints mentioned above --- Cargo.toml | 7 ++++++- crates/bevy_ecs/src/query/state.rs | 4 ++-- crates/bevy_ecs/src/world/unsafe_world_cell.rs | 6 +++--- crates/bevy_mikktspace/src/lib.rs | 3 ++- crates/bevy_ptr/src/lib.rs | 2 +- crates/bevy_utils/src/synccell.rs | 4 +++- crates/bevy_utils/src/syncunsafecell.rs | 7 ++++--- 7 files changed, 21 insertions(+), 12 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7d821c3271..fb180cf432 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,7 +11,7 @@ license = "MIT OR Apache-2.0" readme = "README.md" repository = "https://github.com/bevyengine/bevy" documentation = "https://docs.rs/bevy" -rust-version = "1.74.0" +rust-version = "1.76.0" [workspace] exclude = [ @@ -40,6 +40,11 @@ match_same_arms = "warn" semicolon_if_nothing_returned = "warn" map_flatten = "warn" +ptr_as_ptr = "warn" +ptr_cast_constness = "warn" +#TODO(rust 1.77): enable `ref_as_ptr` +# ref_as_ptr = "warn" + [workspace.lints.rust] unsafe_op_in_unsafe_fn = "warn" missing_docs = "warn" diff --git a/crates/bevy_ecs/src/query/state.rs b/crates/bevy_ecs/src/query/state.rs index ecd544954a..d0c79a3a72 100644 --- a/crates/bevy_ecs/src/query/state.rs +++ b/crates/bevy_ecs/src/query/state.rs @@ -14,7 +14,7 @@ use crate::{ #[cfg(feature = "trace")] use bevy_utils::tracing::Span; use fixedbitset::FixedBitSet; -use std::{any::TypeId, borrow::Borrow, fmt, mem::MaybeUninit}; +use std::{any::TypeId, borrow::Borrow, fmt, mem::MaybeUninit, ptr}; use super::{ NopWorldQuery, QueryBuilder, QueryData, QueryEntityError, QueryFilter, QueryManyIter, @@ -93,7 +93,7 @@ impl QueryState { >( &self, ) -> &QueryState { - &*(self as *const QueryState as *const QueryState) + &*ptr::from_ref(self).cast::>() } /// Returns the archetype components accessed by this query. diff --git a/crates/bevy_ecs/src/world/unsafe_world_cell.rs b/crates/bevy_ecs/src/world/unsafe_world_cell.rs index a851024a70..7ae085d0b2 100644 --- a/crates/bevy_ecs/src/world/unsafe_world_cell.rs +++ b/crates/bevy_ecs/src/world/unsafe_world_cell.rs @@ -17,7 +17,7 @@ use crate::{ system::{Res, Resource}, }; use bevy_ptr::Ptr; -use std::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData}; +use std::{any::TypeId, cell::UnsafeCell, fmt::Debug, marker::PhantomData, ptr}; /// Variant of the [`World`] where resource and component accesses take `&self`, and the responsibility to avoid /// aliasing violations are given to the caller instead of being checked at compile-time by rust's unique XOR shared rule. @@ -85,13 +85,13 @@ impl<'w> UnsafeWorldCell<'w> { /// Creates a [`UnsafeWorldCell`] that can be used to access everything immutably #[inline] pub(crate) fn new_readonly(world: &'w World) -> Self { - UnsafeWorldCell(world as *const World as *mut World, PhantomData) + Self(ptr::from_ref(world).cast_mut(), PhantomData) } /// Creates [`UnsafeWorldCell`] that can be used to access everything mutably #[inline] pub(crate) fn new_mutable(world: &'w mut World) -> Self { - Self(world as *mut World, PhantomData) + Self(ptr::from_mut(world), PhantomData) } /// Gets a mutable reference to the [`World`] this [`UnsafeWorldCell`] belongs to. diff --git a/crates/bevy_mikktspace/src/lib.rs b/crates/bevy_mikktspace/src/lib.rs index b7d43a79da..cbf2c0c7ad 100644 --- a/crates/bevy_mikktspace/src/lib.rs +++ b/crates/bevy_mikktspace/src/lib.rs @@ -1,7 +1,8 @@ #![allow( unsafe_op_in_unsafe_fn, clippy::all, - clippy::undocumented_unsafe_blocks + clippy::undocumented_unsafe_blocks, + clippy::ptr_cast_constness )] // FIXME(3492): remove once docs are ready #![allow(missing_docs)] diff --git a/crates/bevy_ptr/src/lib.rs b/crates/bevy_ptr/src/lib.rs index 73a0ab5555..d26cc1fcb2 100644 --- a/crates/bevy_ptr/src/lib.rs +++ b/crates/bevy_ptr/src/lib.rs @@ -393,7 +393,7 @@ impl<'a, T> Copy for ThinSlicePtr<'a, T> {} impl<'a, T> From<&'a [T]> for ThinSlicePtr<'a, T> { #[inline] fn from(slice: &'a [T]) -> Self { - let ptr = slice.as_ptr() as *mut T; + let ptr = slice.as_ptr().cast_mut(); Self { // SAFETY: a reference can never be null ptr: unsafe { NonNull::new_unchecked(ptr.debug_ensure_aligned()) }, diff --git a/crates/bevy_utils/src/synccell.rs b/crates/bevy_utils/src/synccell.rs index 0ea76cac62..e99c97b7d3 100644 --- a/crates/bevy_utils/src/synccell.rs +++ b/crates/bevy_utils/src/synccell.rs @@ -2,6 +2,8 @@ //! //! [`std::sync::Exclusive`]: https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html +use std::ptr; + /// See [`Exclusive`](https://github.com/rust-lang/rust/issues/98407) for stdlib's upcoming implementation, /// which should replace this one entirely. /// @@ -41,7 +43,7 @@ impl SyncCell { /// to its inner value, to skip constructing with [`new()`](SyncCell::new()). pub fn from_mut(r: &'_ mut T) -> &'_ mut SyncCell { // SAFETY: repr is transparent, so refs have the same layout; and `SyncCell` properties are `&mut`-agnostic - unsafe { &mut *(r as *mut T as *mut SyncCell) } + unsafe { &mut *(ptr::from_mut(r) as *mut SyncCell) } } } diff --git a/crates/bevy_utils/src/syncunsafecell.rs b/crates/bevy_utils/src/syncunsafecell.rs index a2a3ac3885..40a6ea2799 100644 --- a/crates/bevy_utils/src/syncunsafecell.rs +++ b/crates/bevy_utils/src/syncunsafecell.rs @@ -3,6 +3,7 @@ //! [`std::cell::SyncUnsafeCell`]: https://doc.rust-lang.org/nightly/std/cell/struct.SyncUnsafeCell.html pub use core::cell::UnsafeCell; +use core::ptr; /// [`UnsafeCell`], but [`Sync`]. /// @@ -72,13 +73,13 @@ impl SyncUnsafeCell { // We can just cast the pointer from `SyncUnsafeCell` to `T` because // of #[repr(transparent)] on both SyncUnsafeCell and UnsafeCell. // See UnsafeCell::raw_get. - this as *const T as *mut T + (this as *const T).cast_mut() } #[inline] /// Returns a `&mut SyncUnsafeCell` from a `&mut T`. pub fn from_mut(t: &mut T) -> &mut SyncUnsafeCell { - let ptr = t as *mut T as *mut SyncUnsafeCell; + let ptr = ptr::from_mut(t) as *mut SyncUnsafeCell; // SAFETY: `ptr` must be safe to mutably dereference, since it was originally // obtained from a mutable reference. `SyncUnsafeCell` has the same representation // as the original type `T`, since the former is annotated with #[repr(transparent)]. @@ -105,7 +106,7 @@ impl SyncUnsafeCell<[T]> { // - `SyncUnsafeCell` has the same layout as `T` // - `SyncUnsafeCell<[T]>` has the same layout as `[T]` // - `SyncUnsafeCell<[T]>` has the same layout as `[SyncUnsafeCell]` - unsafe { &*(self as *const SyncUnsafeCell<[T]> as *const [SyncUnsafeCell]) } + unsafe { &*(ptr::from_ref(self) as *const [SyncUnsafeCell]) } } }