diff --git a/Cargo.toml b/Cargo.toml index 78725d2084552..bce48e8e4636d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ members = [ [workspace.lints.clippy] type_complexity = "allow" doc_markdown = "warn" +undocumented_unsafe_blocks = "warn" [lints] workspace = true diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index 1e62fa7f10757..e4fdcd360d15a 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -646,6 +646,7 @@ fn apply_animation( let Ok(mut transform) = (unsafe { transforms.get_unchecked(target) }) else { continue; }; + // SAFETY: As above, there can't be other AnimationPlayers with this target so this fetch can't alias let mut morphs = unsafe { morphs.get_unchecked(target) }; for curve in curves { // Some curves have only one keyframe used to set a transform diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index 50b3282e67755..f4e644506f982 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -1,4 +1,3 @@ -#![warn(clippy::undocumented_unsafe_blocks)] #![warn(missing_docs)] #![doc = include_str!("../README.md")] diff --git a/crates/bevy_mikktspace/src/lib.rs b/crates/bevy_mikktspace/src/lib.rs index 89d7b05427407..5d9e2e0d8ac07 100644 --- a/crates/bevy_mikktspace/src/lib.rs +++ b/crates/bevy_mikktspace/src/lib.rs @@ -1,4 +1,4 @@ -#![allow(clippy::all)] +#![allow(clippy::all, clippy::undocumented_unsafe_blocks)] use glam::{Vec2, Vec3}; diff --git a/crates/bevy_ptr/src/lib.rs b/crates/bevy_ptr/src/lib.rs index 7a98d53b9f018..bebfc7de51a4c 100644 --- a/crates/bevy_ptr/src/lib.rs +++ b/crates/bevy_ptr/src/lib.rs @@ -244,14 +244,14 @@ impl<'a, A: IsAligned> PtrMut<'a, A> { /// Gets a [`PtrMut`] from this with a smaller lifetime. #[inline] pub fn reborrow(&mut self) -> PtrMut<'_, A> { - // SAFE: the ptrmut we're borrowing from is assumed to be valid + // SAFETY: the ptrmut we're borrowing from is assumed to be valid unsafe { PtrMut::new(self.0) } } /// Gets an immutable reference from this mutable reference #[inline] pub fn as_ref(&self) -> Ptr<'_, A> { - // SAFE: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees + // SAFETY: The `PtrMut` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees unsafe { Ptr::new(self.0) } } } @@ -327,14 +327,14 @@ impl<'a, A: IsAligned> OwningPtr<'a, A> { /// Gets an immutable pointer from this owned pointer. #[inline] pub fn as_ref(&self) -> Ptr<'_, A> { - // SAFE: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees + // SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees unsafe { Ptr::new(self.0) } } /// Gets a mutable pointer from this owned pointer. #[inline] pub fn as_mut(&mut self) -> PtrMut<'_, A> { - // SAFE: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees + // SAFETY: The `Owning` type's guarantees about the validity of this pointer are a superset of `Ptr` s guarantees unsafe { PtrMut::new(self.0) } } } diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index cde3062c480cd..9e560f22ad855 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -251,6 +251,7 @@ impl Plugin for RenderPlugin { app.insert_resource(FutureRendererResources( future_renderer_resources_wrapper.clone(), )); + // SAFETY: Plugins should be set up on the main thread. unsafe { initialize_render_app(app) }; } RenderCreation::Automatic(render_creation) => { @@ -271,8 +272,8 @@ impl Plugin for RenderPlugin { backends, dx12_shader_compiler: settings.dx12_shader_compiler.clone(), }); + // SAFETY: Plugins should be set up on the main thread. let surface = primary_window.map(|wrapper| unsafe { - // SAFETY: Plugins should be set up on the main thread. let handle = wrapper.get_handle(); instance .create_surface(&handle) @@ -313,6 +314,7 @@ impl Plugin for RenderPlugin { #[cfg(not(target_arch = "wasm32"))] futures_lite::future::block_on(async_renderer); + // SAFETY: Plugins should be set up on the main thread. unsafe { initialize_render_app(app) }; } } @@ -453,7 +455,7 @@ unsafe fn initialize_render_app(app: &mut App) { "An entity was spawned after the entity list was cleared last frame and before the extract schedule began. This is not supported", ); - // This is safe given the clear_entities call in the past frame and the assert above + // SAFETY: This is safe given the clear_entities call in the past frame and the assert above unsafe { render_app .world diff --git a/crates/bevy_render/src/render_resource/resource_macros.rs b/crates/bevy_render/src/render_resource/resource_macros.rs index a827fcc7ba3fb..ab5ce2cbebe19 100644 --- a/crates/bevy_render/src/render_resource/resource_macros.rs +++ b/crates/bevy_render/src/render_resource/resource_macros.rs @@ -58,6 +58,7 @@ macro_rules! render_resource_wrapper { // If in future there is a case where a wrapper is required for a non-send/sync type // we can implement a macro variant that omits these manual Send + Sync impls unsafe impl Send for $wrapper_type {} + // SAFETY: As explained above, we ensure correctness by checking that $wgpu_type implements Send and Sync. unsafe impl Sync for $wrapper_type {} const _: () = { trait AssertSendSyncBound: Send + Sync {} diff --git a/crates/bevy_render/src/view/window/mod.rs b/crates/bevy_render/src/view/window/mod.rs index 31ac4fca2cee3..b9e62c6a6b151 100644 --- a/crates/bevy_render/src/view/window/mod.rs +++ b/crates/bevy_render/src/view/window/mod.rs @@ -252,12 +252,15 @@ pub fn prepare_windows( let surface_data = window_surfaces .surfaces .entry(window.entity) - .or_insert_with(|| unsafe { - // NOTE: On some OSes this MUST be called from the main thread. - // As of wgpu 0.15, only fallible if the given window is a HTML canvas and obtaining a WebGPU or WebGL2 context fails. - let surface = render_instance - .create_surface(&window.handle.get_handle()) - .expect("Failed to create wgpu surface"); + .or_insert_with(|| { + // SAFETY: The window handles in ExtractedWindows will always be valid objects to create surfaces on + let surface = unsafe { + // NOTE: On some OSes this MUST be called from the main thread. + // As of wgpu 0.15, only fallible if the given window is a HTML canvas and obtaining a WebGPU or WebGL2 context fails. + render_instance + .create_surface(&window.handle.get_handle()) + .expect("Failed to create wgpu surface") + }; let caps = surface.get_capabilities(&render_adapter); let formats = caps.formats; // For future HDR output support, we'll need to request a format that supports HDR, diff --git a/crates/bevy_tasks/src/task_pool.rs b/crates/bevy_tasks/src/task_pool.rs index b538705b6742b..4c37ef3b7a190 100644 --- a/crates/bevy_tasks/src/task_pool.rs +++ b/crates/bevy_tasks/src/task_pool.rs @@ -353,12 +353,16 @@ impl TaskPool { // Any usages of the references passed into `Scope` must be accessed through // the transmuted reference for the rest of this function. let executor: &async_executor::Executor = &self.executor; + // SAFETY: As above, all futures must complete in this function so we can change the lifetime let executor: &'env async_executor::Executor = unsafe { mem::transmute(executor) }; + // SAFETY: As above, all futures must complete in this function so we can change the lifetime let external_executor: &'env ThreadExecutor<'env> = unsafe { mem::transmute(external_executor) }; + // SAFETY: As above, all futures must complete in this function so we can change the lifetime let scope_executor: &'env ThreadExecutor<'env> = unsafe { mem::transmute(scope_executor) }; let spawned: ConcurrentQueue> = ConcurrentQueue::unbounded(); // shadow the variable so that the owned value cannot be used for the rest of the function + // SAFETY: As above, all futures must complete in this function so we can change the lifetime let spawned: &'env ConcurrentQueue< FallibleTask>>, > = unsafe { mem::transmute(&spawned) }; @@ -373,6 +377,7 @@ impl TaskPool { }; // shadow the variable so that the owned value cannot be used for the rest of the function + // SAFETY: As above, all futures must complete in this function so we can change the lifetime let scope: &'env Scope<'_, 'env, T> = unsafe { mem::transmute(&scope) }; f(scope); diff --git a/crates/bevy_transform/src/lib.rs b/crates/bevy_transform/src/lib.rs index db7d1805a80bb..c7d16ea989a13 100644 --- a/crates/bevy_transform/src/lib.rs +++ b/crates/bevy_transform/src/lib.rs @@ -1,5 +1,4 @@ #![warn(missing_docs)] -#![warn(clippy::undocumented_unsafe_blocks)] #![doc = include_str!("../README.md")] pub mod commands; diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index a02308566b446..2425d7fdb0c74 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1309,6 +1309,7 @@ pub struct GridPlacement { impl GridPlacement { pub const DEFAULT: Self = Self { start: None, + // SAFETY: This is trivially safe as 1 is non-zero. span: Some(unsafe { NonZeroU16::new_unchecked(1) }), end: None, }; diff --git a/crates/bevy_utils/src/lib.rs b/crates/bevy_utils/src/lib.rs index 534edbd76218c..320bb407c9096 100644 --- a/crates/bevy_utils/src/lib.rs +++ b/crates/bevy_utils/src/lib.rs @@ -4,7 +4,6 @@ //! #![warn(missing_docs)] -#![warn(clippy::undocumented_unsafe_blocks)] #[allow(missing_docs)] pub mod prelude { diff --git a/crates/bevy_window/src/raw_handle.rs b/crates/bevy_window/src/raw_handle.rs index 06b36ee9ceb6a..580de90b293b7 100644 --- a/crates/bevy_window/src/raw_handle.rs +++ b/crates/bevy_window/src/raw_handle.rs @@ -34,6 +34,7 @@ impl RawHandleWrapper { // A recommendation for this pattern (and more context) is available here: // https://github.com/rust-windowing/raw-window-handle/issues/59 unsafe impl Send for RawHandleWrapper {} +// SAFETY: This is safe for the same reasons as the Send impl above. unsafe impl Sync for RawHandleWrapper {} /// A [`RawHandleWrapper`] that cannot be sent across threads.