From 56bcbb097552b45e3ff48c48947ed8ee4e2c24b1 Mon Sep 17 00:00:00 2001 From: James Liu Date: Tue, 26 Mar 2024 20:30:08 -0700 Subject: [PATCH] Forbid unsafe in most crates in the engine (#12684) # Objective Resolves #3824. `unsafe` code should be the exception, not the norm in Rust. It's obviously needed for various use cases as it's interfacing with platforms and essentially running the borrow checker at runtime in the ECS, but the touted benefits of Bevy is that we are able to heavily leverage Rust's safety, and we should be holding ourselves accountable to that by minimizing our unsafe footprint. ## Solution Deny `unsafe_code` workspace wide. Add explicit exceptions for the following crates, and forbid it in almost all of the others. * bevy_ecs - Obvious given how much unsafe is needed to achieve performant results * bevy_ptr - Works with raw pointers, even more low level than bevy_ecs. * bevy_render - due to needing to integrate with wgpu * bevy_window - due to needing to integrate with raw_window_handle * bevy_utils - Several unsafe utilities used by bevy_ecs. Ideally moved into bevy_ecs instead of made publicly usable. * bevy_reflect - Required for the unsafe type casting it's doing. * bevy_transform - for the parallel transform propagation * bevy_gizmos - For the SystemParam impls it has. * bevy_assets - To support reflection. Might not be required, not 100% sure yet. * bevy_mikktspace - due to being a conversion from a C library. Pending safe rewrite. * bevy_dynamic_plugin - Inherently unsafe due to the dynamic loading nature. Several uses of unsafe were rewritten, as they did not need to be using them: * bevy_text - a case of `Option::unchecked` could be rewritten as a normal for loop and match instead of an iterator. * bevy_color - the Pod/Zeroable implementations were replaceable with bytemuck's derive macros. --- Cargo.toml | 1 + crates/bevy_animation/src/lib.rs | 1 + crates/bevy_app/src/lib.rs | 1 + crates/bevy_asset/src/reflect.rs | 3 ++ crates/bevy_color/src/lib.rs | 1 + crates/bevy_color/src/linear_rgba.rs | 29 +--------------- crates/bevy_core/src/lib.rs | 1 + crates/bevy_core_pipeline/src/lib.rs | 1 + crates/bevy_derive/src/lib.rs | 1 + crates/bevy_dev_tools/src/lib.rs | 1 + crates/bevy_diagnostic/src/lib.rs | 1 + crates/bevy_dynamic_plugin/src/loader.rs | 2 ++ crates/bevy_ecs/src/lib.rs | 1 + crates/bevy_encase_derive/src/lib.rs | 1 + crates/bevy_gilrs/src/lib.rs | 1 + crates/bevy_gizmos/src/gizmos.rs | 4 +++ crates/bevy_gltf/src/lib.rs | 1 + crates/bevy_hierarchy/src/lib.rs | 1 + crates/bevy_input/src/lib.rs | 1 + crates/bevy_internal/src/lib.rs | 1 + crates/bevy_log/src/android_tracing.rs | 1 + crates/bevy_macro_utils/src/lib.rs | 2 +- crates/bevy_math/src/lib.rs | 1 + crates/bevy_mikktspace/src/generated.rs | 3 +- crates/bevy_mikktspace/src/lib.rs | 1 + .../bevy_pbr/src/meshlet/persistent_buffer.rs | 2 ++ .../src/meshlet/persistent_buffer_impls.rs | 1 + crates/bevy_ptr/src/lib.rs | 1 + crates/bevy_reflect/src/path/parse.rs | 1 + crates/bevy_reflect/src/type_registry.rs | 3 ++ crates/bevy_render/src/lib.rs | 1 + crates/bevy_scene/src/lib.rs | 1 + crates/bevy_sprite/src/lib.rs | 1 + .../src/single_threaded_task_pool.rs | 1 + crates/bevy_tasks/src/task_pool.rs | 1 + crates/bevy_text/src/lib.rs | 1 + crates/bevy_text/src/pipeline.rs | 33 ++++++++----------- crates/bevy_time/src/lib.rs | 1 + crates/bevy_transform/src/systems.rs | 2 ++ crates/bevy_ui/src/ui_node.rs | 1 + crates/bevy_utils/src/lib.rs | 1 + crates/bevy_window/src/raw_handle.rs | 2 ++ crates/bevy_winit/src/lib.rs | 1 + examples/ecs/dynamic.rs | 2 ++ 44 files changed, 69 insertions(+), 50 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6d5c3cdc422c4..b06f1642f33c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,7 @@ ptr_cast_constness = "warn" [workspace.lints.rust] unsafe_op_in_unsafe_fn = "warn" missing_docs = "warn" +unsafe_code = "deny" [lints] workspace = true diff --git a/crates/bevy_animation/src/lib.rs b/crates/bevy_animation/src/lib.rs index 1b1a65dddec92..c4f8bc9248e6b 100644 --- a/crates/bevy_animation/src/lib.rs +++ b/crates/bevy_animation/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_app/src/lib.rs b/crates/bevy_app/src/lib.rs index 6b5e73b531550..d231780c4ae7f 100644 --- a/crates/bevy_app/src/lib.rs +++ b/crates/bevy_app/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_asset/src/reflect.rs b/crates/bevy_asset/src/reflect.rs index 41d8911270026..02e8cd85278b1 100644 --- a/crates/bevy_asset/src/reflect.rs +++ b/crates/bevy_asset/src/reflect.rs @@ -46,6 +46,7 @@ impl ReflectAsset { } /// Equivalent of [`Assets::get_mut`] + #[allow(unsafe_code)] pub fn get_mut<'w>( &self, world: &'w mut World, @@ -82,6 +83,7 @@ impl ReflectAsset { /// violating Rust's aliasing rules. To avoid this: /// * Only call this method if you know that the [`UnsafeWorldCell`] may be used to access the corresponding `Assets` /// * Don't call this method more than once in the same scope. + #[allow(unsafe_code)] pub unsafe fn get_unchecked_mut<'w>( &self, world: UnsafeWorldCell<'w>, @@ -135,6 +137,7 @@ impl FromType for ReflectAsset { get_unchecked_mut: |world, handle| { // SAFETY: `get_unchecked_mut` must be called with `UnsafeWorldCell` having access to `Assets`, // and must ensure to only have at most one reference to it live at all times. + #[allow(unsafe_code)] let assets = unsafe { world.get_resource_mut::>().unwrap().into_inner() }; let asset = assets.get_mut(&handle.typed_debug_checked()); asset.map(|asset| asset as &mut dyn Reflect) diff --git a/crates/bevy_color/src/lib.rs b/crates/bevy_color/src/lib.rs index 648dbd0ace6bf..c9c6b49381fd3 100644 --- a/crates/bevy_color/src/lib.rs +++ b/crates/bevy_color/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_color/src/linear_rgba.rs b/crates/bevy_color/src/linear_rgba.rs index 8f0cd071f1b33..ef5fa40b5bf19 100644 --- a/crates/bevy_color/src/linear_rgba.rs +++ b/crates/bevy_color/src/linear_rgba.rs @@ -11,7 +11,7 @@ use bytemuck::{Pod, Zeroable}; ///
#[doc = include_str!("../docs/diagrams/model_graph.svg")] ///
-#[derive(Debug, Clone, Copy, PartialEq, Reflect)] +#[derive(Debug, Clone, Copy, PartialEq, Reflect, Pod, Zeroable)] #[reflect(PartialEq, Default)] #[cfg_attr( feature = "serialize", @@ -373,33 +373,6 @@ impl encase::private::CreateFrom for LinearRgba { } } -/// A [`Zeroable`] type is one whose bytes can be filled with zeroes while remaining valid. -/// -/// SAFETY: [`LinearRgba`] is inhabited -/// SAFETY: [`LinearRgba`]'s all-zero bit pattern is a valid value -unsafe impl Zeroable for LinearRgba { - fn zeroed() -> Self { - LinearRgba { - red: 0.0, - green: 0.0, - blue: 0.0, - alpha: 0.0, - } - } -} - -/// The [`Pod`] trait is [`bytemuck`]'s marker for types that can be safely transmuted from a byte array. -/// -/// It is intended to only be implemented for types which are "Plain Old Data". -/// -/// SAFETY: [`LinearRgba`] is inhabited. -/// SAFETY: [`LinearRgba`] permits any bit value. -/// SAFETY: [`LinearRgba`] does not have padding bytes. -/// SAFETY: all of the fields of [`LinearRgba`] are [`Pod`], as f32 is [`Pod`]. -/// SAFETY: [`LinearRgba`] is `repr(C)` -/// SAFETY: [`LinearRgba`] does not permit interior mutability. -unsafe impl Pod for LinearRgba {} - impl encase::ShaderSize for LinearRgba {} #[cfg(test)] diff --git a/crates/bevy_core/src/lib.rs b/crates/bevy_core/src/lib.rs index 98aaacf1fc4ec..b636122c17b23 100644 --- a/crates/bevy_core/src/lib.rs +++ b/crates/bevy_core/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_core_pipeline/src/lib.rs b/crates/bevy_core_pipeline/src/lib.rs index 1bb70708c30d7..9bb44c4e33116 100644 --- a/crates/bevy_core_pipeline/src/lib.rs +++ b/crates/bevy_core_pipeline/src/lib.rs @@ -1,5 +1,6 @@ // FIXME(3492): remove once docs are ready #![allow(missing_docs)] +#![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", diff --git a/crates/bevy_derive/src/lib.rs b/crates/bevy_derive/src/lib.rs index fc16ec34642a3..576b26bf99c18 100644 --- a/crates/bevy_derive/src/lib.rs +++ b/crates/bevy_derive/src/lib.rs @@ -1,5 +1,6 @@ // FIXME(3492): remove once docs are ready #![allow(missing_docs)] +#![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", diff --git a/crates/bevy_dev_tools/src/lib.rs b/crates/bevy_dev_tools/src/lib.rs index 4b745984b4590..d244873160d72 100644 --- a/crates/bevy_dev_tools/src/lib.rs +++ b/crates/bevy_dev_tools/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_diagnostic/src/lib.rs b/crates/bevy_diagnostic/src/lib.rs index 9a07eb50407b6..bb0fb5d41d537 100644 --- a/crates/bevy_diagnostic/src/lib.rs +++ b/crates/bevy_diagnostic/src/lib.rs @@ -1,6 +1,7 @@ // FIXME(3492): remove once docs are ready #![allow(missing_docs)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_dynamic_plugin/src/loader.rs b/crates/bevy_dynamic_plugin/src/loader.rs index 94c283a886e78..8b6517b237244 100644 --- a/crates/bevy_dynamic_plugin/src/loader.rs +++ b/crates/bevy_dynamic_plugin/src/loader.rs @@ -1,3 +1,5 @@ +#![allow(unsafe_code)] + use libloading::{Library, Symbol}; use std::ffi::OsStr; use thiserror::Error; diff --git a/crates/bevy_ecs/src/lib.rs b/crates/bevy_ecs/src/lib.rs index a88c97e99b4ab..4626fbd6c2d07 100644 --- a/crates/bevy_ecs/src/lib.rs +++ b/crates/bevy_ecs/src/lib.rs @@ -2,6 +2,7 @@ #![allow(unsafe_op_in_unsafe_fn)] #![doc = include_str!("../README.md")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![allow(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_encase_derive/src/lib.rs b/crates/bevy_encase_derive/src/lib.rs index b0c266b70b72e..a6d225dff1f8a 100644 --- a/crates/bevy_encase_derive/src/lib.rs +++ b/crates/bevy_encase_derive/src/lib.rs @@ -1,5 +1,6 @@ // FIXME(3492): remove once docs are ready #![allow(missing_docs)] +#![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", diff --git a/crates/bevy_gilrs/src/lib.rs b/crates/bevy_gilrs/src/lib.rs index 5d076f3f2e485..0b03ea23df442 100644 --- a/crates/bevy_gilrs/src/lib.rs +++ b/crates/bevy_gilrs/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_gizmos/src/gizmos.rs b/crates/bevy_gizmos/src/gizmos.rs index 5bf72159516f9..f161792bcaf2f 100644 --- a/crates/bevy_gizmos/src/gizmos.rs +++ b/crates/bevy_gizmos/src/gizmos.rs @@ -49,6 +49,8 @@ type GizmosState = ( pub struct GizmosFetchState { state: as SystemParam>::State, } + +#[allow(unsafe_code)] // SAFETY: All methods are delegated to existing `SystemParam` implementations unsafe impl SystemParam for Gizmos<'_, '_, T> { type State = GizmosFetchState; @@ -90,6 +92,8 @@ unsafe impl SystemParam for Gizmos<'_, '_, T> { } } } + +#[allow(unsafe_code)] // Safety: Each field is `ReadOnlySystemParam`, and Gizmos SystemParam does not mutate world unsafe impl<'w, 's, T: GizmoConfigGroup> ReadOnlySystemParam for Gizmos<'w, 's, T> where diff --git a/crates/bevy_gltf/src/lib.rs b/crates/bevy_gltf/src/lib.rs index c4b5986467f8b..9133f3128430b 100644 --- a/crates/bevy_gltf/src/lib.rs +++ b/crates/bevy_gltf/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_hierarchy/src/lib.rs b/crates/bevy_hierarchy/src/lib.rs index a27b3b4f47b2b..53e00f5a768cb 100644 --- a/crates/bevy_hierarchy/src/lib.rs +++ b/crates/bevy_hierarchy/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_input/src/lib.rs b/crates/bevy_input/src/lib.rs index 6d469c7e80faa..17d392583f27d 100644 --- a/crates/bevy_input/src/lib.rs +++ b/crates/bevy_input/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_internal/src/lib.rs b/crates/bevy_internal/src/lib.rs index cfbfe08ae3999..5bb91b57aee60 100644 --- a/crates/bevy_internal/src/lib.rs +++ b/crates/bevy_internal/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_log/src/android_tracing.rs b/crates/bevy_log/src/android_tracing.rs index a5e7bc8626b2e..80a9b63c538a8 100644 --- a/crates/bevy_log/src/android_tracing.rs +++ b/crates/bevy_log/src/android_tracing.rs @@ -73,6 +73,7 @@ impl LookupSpan<'a>> Layer for AndroidLayer { } } + #[allow(unsafe_code)] fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) { let mut recorder = StringRecorder::new(); event.record(&mut recorder); diff --git a/crates/bevy_macro_utils/src/lib.rs b/crates/bevy_macro_utils/src/lib.rs index ce1d53f2e8d2e..28de7e2227e26 100644 --- a/crates/bevy_macro_utils/src/lib.rs +++ b/crates/bevy_macro_utils/src/lib.rs @@ -1,4 +1,4 @@ -#![deny(unsafe_code)] +#![forbid(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", diff --git a/crates/bevy_math/src/lib.rs b/crates/bevy_math/src/lib.rs index 9d7962e7fe993..1a37c53f4e987 100644 --- a/crates/bevy_math/src/lib.rs +++ b/crates/bevy_math/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_mikktspace/src/generated.rs b/crates/bevy_mikktspace/src/generated.rs index a69b1e8a27281..91c697b3299d9 100644 --- a/crates/bevy_mikktspace/src/generated.rs +++ b/crates/bevy_mikktspace/src/generated.rs @@ -41,7 +41,8 @@ non_upper_case_globals, unused_mut, unused_assignments, - unused_variables + unused_variables, + unsafe_code )] use std::ptr::null_mut; diff --git a/crates/bevy_mikktspace/src/lib.rs b/crates/bevy_mikktspace/src/lib.rs index 7f067b3d2bc86..d383f8ad5c447 100644 --- a/crates/bevy_mikktspace/src/lib.rs +++ b/crates/bevy_mikktspace/src/lib.rs @@ -67,6 +67,7 @@ pub trait Geometry { /// /// Returns `false` if the geometry is unsuitable for tangent generation including, /// but not limited to, lack of vertices. +#[allow(unsafe_code)] pub fn generate_tangents(geometry: &mut I) -> bool { unsafe { generated::genTangSpace(geometry, 180.0) } } diff --git a/crates/bevy_pbr/src/meshlet/persistent_buffer.rs b/crates/bevy_pbr/src/meshlet/persistent_buffer.rs index eccce560dca55..fe67b1841658b 100644 --- a/crates/bevy_pbr/src/meshlet/persistent_buffer.rs +++ b/crates/bevy_pbr/src/meshlet/persistent_buffer.rs @@ -1,3 +1,5 @@ +#![allow(unsafe_code)] + use bevy_render::{ render_resource::{ BindingResource, Buffer, BufferAddress, BufferDescriptor, BufferUsages, diff --git a/crates/bevy_pbr/src/meshlet/persistent_buffer_impls.rs b/crates/bevy_pbr/src/meshlet/persistent_buffer_impls.rs index 0567246b3543f..b3e882dc43143 100644 --- a/crates/bevy_pbr/src/meshlet/persistent_buffer_impls.rs +++ b/crates/bevy_pbr/src/meshlet/persistent_buffer_impls.rs @@ -1,3 +1,4 @@ +#![allow(unsafe_code)] #![allow(clippy::undocumented_unsafe_blocks)] use super::{persistent_buffer::PersistentGpuBufferable, Meshlet, MeshletBoundingSphere}; diff --git a/crates/bevy_ptr/src/lib.rs b/crates/bevy_ptr/src/lib.rs index 79dc0f320502d..aae2a4dfd8414 100644 --- a/crates/bevy_ptr/src/lib.rs +++ b/crates/bevy_ptr/src/lib.rs @@ -1,6 +1,7 @@ #![doc = include_str!("../README.md")] #![no_std] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![allow(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_reflect/src/path/parse.rs b/crates/bevy_reflect/src/path/parse.rs index 1a90586859ec9..8195a23a31cb4 100644 --- a/crates/bevy_reflect/src/path/parse.rs +++ b/crates/bevy_reflect/src/path/parse.rs @@ -65,6 +65,7 @@ impl<'a> PathParser<'a> { // the last byte before an ASCII utf-8 character (ie: it is a char // boundary). // - The slice always starts after a symbol ie: an ASCII character's boundary. + #[allow(unsafe_code)] let ident = unsafe { from_utf8_unchecked(ident) }; self.remaining = remaining; diff --git a/crates/bevy_reflect/src/type_registry.rs b/crates/bevy_reflect/src/type_registry.rs index 2846781f47792..2090094fea70a 100644 --- a/crates/bevy_reflect/src/type_registry.rs +++ b/crates/bevy_reflect/src/type_registry.rs @@ -663,6 +663,7 @@ pub struct ReflectFromPtr { from_ptr_mut: unsafe fn(PtrMut) -> &mut dyn Reflect, } +#[allow(unsafe_code)] impl ReflectFromPtr { /// Returns the [`TypeId`] that the [`ReflectFromPtr`] was constructed for. pub fn type_id(&self) -> TypeId { @@ -714,6 +715,7 @@ impl ReflectFromPtr { } } +#[allow(unsafe_code)] impl FromType for ReflectFromPtr { fn from_type() -> Self { ReflectFromPtr { @@ -733,6 +735,7 @@ impl FromType for ReflectFromPtr { } #[cfg(test)] +#[allow(unsafe_code)] mod test { use crate::{GetTypeRegistration, ReflectFromPtr}; use bevy_ptr::{Ptr, PtrMut}; diff --git a/crates/bevy_render/src/lib.rs b/crates/bevy_render/src/lib.rs index fba46c10189fd..72c30775f4c5f 100644 --- a/crates/bevy_render/src/lib.rs +++ b/crates/bevy_render/src/lib.rs @@ -1,5 +1,6 @@ // FIXME(3492): remove once docs are ready #![allow(missing_docs)] +#![allow(unsafe_code)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", diff --git a/crates/bevy_scene/src/lib.rs b/crates/bevy_scene/src/lib.rs index 479ea497f769f..0c1a89785412f 100644 --- a/crates/bevy_scene/src/lib.rs +++ b/crates/bevy_scene/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_sprite/src/lib.rs b/crates/bevy_sprite/src/lib.rs index afa1311736357..de6e35e4489b6 100644 --- a/crates/bevy_sprite/src/lib.rs +++ b/crates/bevy_sprite/src/lib.rs @@ -1,6 +1,7 @@ // FIXME(3492): remove once docs are ready #![allow(missing_docs)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_tasks/src/single_threaded_task_pool.rs b/crates/bevy_tasks/src/single_threaded_task_pool.rs index f3837c4766fae..3a32c9e286211 100644 --- a/crates/bevy_tasks/src/single_threaded_task_pool.rs +++ b/crates/bevy_tasks/src/single_threaded_task_pool.rs @@ -94,6 +94,7 @@ impl TaskPool { /// to spawn tasks. This function will await the completion of all tasks before returning. /// /// This is similar to `rayon::scope` and `crossbeam::scope` + #[allow(unsafe_code)] pub fn scope_with_executor<'env, F, T>( &self, _tick_task_pool_executor: bool, diff --git a/crates/bevy_tasks/src/task_pool.rs b/crates/bevy_tasks/src/task_pool.rs index 551bb06311fd2..300373031ad42 100644 --- a/crates/bevy_tasks/src/task_pool.rs +++ b/crates/bevy_tasks/src/task_pool.rs @@ -334,6 +334,7 @@ impl TaskPool { }) } + #[allow(unsafe_code)] fn scope_with_executor_inner<'env, F, T>( &self, tick_task_pool_executor: bool, diff --git a/crates/bevy_text/src/lib.rs b/crates/bevy_text/src/lib.rs index 3a5c57c762639..839418174330c 100644 --- a/crates/bevy_text/src/lib.rs +++ b/crates/bevy_text/src/lib.rs @@ -1,6 +1,7 @@ // FIXME(3492): remove once docs are ready #![allow(missing_docs)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_text/src/pipeline.rs b/crates/bevy_text/src/pipeline.rs index edd76a2de9ec0..26c547466e05f 100644 --- a/crates/bevy_text/src/pipeline.rs +++ b/crates/bevy_text/src/pipeline.rs @@ -129,32 +129,25 @@ impl TextMeasureInfo { scale_factor: f32, ) -> Result { let sections = &text.sections; - for section in sections { - if !fonts.contains(§ion.style.font) { - return Err(TextError::NoSuchFont); - } - } - let (auto_fonts, sections) = sections - .iter() - .enumerate() - .map(|(i, section)| { - // SAFETY: we exited early earlier in this function if - // one of the fonts was missing. - let font = unsafe { fonts.get(§ion.style.font).unwrap_unchecked() }; - ( - font.font.clone(), - TextMeasureSection { + let mut auto_fonts = Vec::with_capacity(sections.len()); + let mut out_sections = Vec::with_capacity(sections.len()); + for (i, section) in sections.iter().enumerate() { + match fonts.get(§ion.style.font) { + Some(font) => { + auto_fonts.push(font.font.clone()); + out_sections.push(TextMeasureSection { font_id: FontId(i), scale: scale_value(section.style.font_size, scale_factor), text: section.value.clone().into_boxed_str(), - }, - ) - }) - .unzip(); + }); + } + None => return Err(TextError::NoSuchFont), + } + } Ok(Self::new( auto_fonts, - sections, + out_sections, text.justify, text.linebreak_behavior.into(), )) diff --git a/crates/bevy_time/src/lib.rs b/crates/bevy_time/src/lib.rs index 03b34b8a72f81..3119f023523e9 100644 --- a/crates/bevy_time/src/lib.rs +++ b/crates/bevy_time/src/lib.rs @@ -1,5 +1,6 @@ #![doc = include_str!("../README.md")] #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_transform/src/systems.rs b/crates/bevy_transform/src/systems.rs index bdbce91e941bb..4e0a2efe8fa2e 100644 --- a/crates/bevy_transform/src/systems.rs +++ b/crates/bevy_transform/src/systems.rs @@ -79,6 +79,7 @@ pub fn propagate_transforms( // - Since each root entity is unique and the hierarchy is consistent and forest-like, // other root entities' `propagate_recursive` calls will not conflict with this one. // - Since this is the only place where `transform_query` gets used, there will be no conflicting fetches elsewhere. + #[allow(unsafe_code)] unsafe { propagate_recursive( &global_transform, @@ -106,6 +107,7 @@ pub fn propagate_transforms( /// nor any of its descendants. /// - The caller must ensure that the hierarchy leading to `entity` /// is well-formed and must remain as a tree or a forest. Each entity must have at most one parent. +#[allow(unsafe_code)] unsafe fn propagate_recursive( parent: &GlobalTransform, transform_query: &Query< diff --git a/crates/bevy_ui/src/ui_node.rs b/crates/bevy_ui/src/ui_node.rs index 272220f3d52ae..41be40d3be37f 100644 --- a/crates/bevy_ui/src/ui_node.rs +++ b/crates/bevy_ui/src/ui_node.rs @@ -1424,6 +1424,7 @@ pub struct GridPlacement { } impl GridPlacement { + #[allow(unsafe_code)] pub const DEFAULT: Self = Self { start: None, // SAFETY: This is trivially safe as 1 is non-zero. diff --git a/crates/bevy_utils/src/lib.rs b/crates/bevy_utils/src/lib.rs index d3e67acf54af3..eec2f08367813 100644 --- a/crates/bevy_utils/src/lib.rs +++ b/crates/bevy_utils/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![allow(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/crates/bevy_window/src/raw_handle.rs b/crates/bevy_window/src/raw_handle.rs index f9b6336149c61..eb9382590c883 100644 --- a/crates/bevy_window/src/raw_handle.rs +++ b/crates/bevy_window/src/raw_handle.rs @@ -1,3 +1,5 @@ +#![allow(unsafe_code)] + use bevy_ecs::prelude::Component; use raw_window_handle::{ DisplayHandle, HandleError, HasDisplayHandle, HasWindowHandle, RawDisplayHandle, diff --git a/crates/bevy_winit/src/lib.rs b/crates/bevy_winit/src/lib.rs index 7d348c7c80952..893937d5f2696 100644 --- a/crates/bevy_winit/src/lib.rs +++ b/crates/bevy_winit/src/lib.rs @@ -1,4 +1,5 @@ #![cfg_attr(docsrs, feature(doc_auto_cfg))] +#![forbid(unsafe_code)] #![doc( html_logo_url = "https://bevyengine.org/assets/icon.png", html_favicon_url = "https://bevyengine.org/assets/icon.png" diff --git a/examples/ecs/dynamic.rs b/examples/ecs/dynamic.rs index 9b0c41ef04f6b..d5f18e059c313 100644 --- a/examples/ecs/dynamic.rs +++ b/examples/ecs/dynamic.rs @@ -1,3 +1,5 @@ +#![allow(unsafe_code)] + //! This example show how you can create components dynamically, spawn entities with those components //! as well as query for entities with those components.