Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forbid unsafe in most crates in the engine #12684

Merged
merged 26 commits into from
Mar 27, 2024

Conversation

james7132
Copy link
Member

@james7132 james7132 commented Mar 24, 2024

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.

@james7132 james7132 added C-Code-Quality A section of code that is hard to understand or change P-Unsound A bug that results in undefined compiler behavior A-Cross-Cutting Impacts the entire engine labels Mar 24, 2024
@james7132 james7132 changed the title Forbid unsafe Forbid unsafe in most crates in the engine Mar 24, 2024
Copy link
Contributor

@bushrat011899 bushrat011899 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Definitely a good change. Ideally, Bevy would contain zero unsafe code. While that may be impossible, it's still worth minimising the risk.

@@ -1,3 +1,5 @@
#![allow(unsafe_code)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😂 No targeted allows here.

.map(|(i, section)| {
// SAFETY: we exited early earlier in this function if
// one of the fonts was missing.
let font = unsafe { fonts.get(&section.style.font).unwrap_unchecked() };
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good choice, this is the sort of needless unsafe I was hoping to clean up.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Mar 24, 2024
@alice-i-cecile alice-i-cecile added this pull request to the merge queue Mar 25, 2024
@james7132 james7132 removed this pull request from the merge queue due to a manual request Mar 25, 2024
@james7132 james7132 enabled auto-merge March 25, 2024 19:33
@alice-i-cecile alice-i-cecile disabled auto-merge March 25, 2024 19:57
@alice-i-cecile
Copy link
Member

@james7132 @JMS55 @rodolphito Meshlets added new unsafe code that will need to be allowed to get this mergeable.

@james7132
Copy link
Member Author

@JMS55 is there a reason why PersistentGpuBufferable is an unsafe trait? Both of it's functions are not used in an unsafe context without existing safety checks.

@JMS55
Copy link
Contributor

JMS55 commented Mar 25, 2024

Iirc it's because there's no checks for it, but the data has to be 4 byte aligned (or whatever wgpu wants), and it needs to accurately report the size in one function that then gets written in the second.

@james7132
Copy link
Member Author

If that's the case, the APIs on wgpu's end need to be unsafe, which I don't think is the case. As far as CPU-side memory safety goes, this looks safe to me, even if the implementation of the trait is wrong.

@james7132 james7132 added this pull request to the merge queue Mar 26, 2024
@github-merge-queue github-merge-queue bot removed this pull request from the merge queue due to failed status checks Mar 26, 2024
Copy link
Member

@BD103 BD103 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! What's your reason for forbid-ing many of the crates when they already inherit deny from the workspace?

@alice-i-cecile
Copy link
Member

Forbid can't be locally allowed. In crates where we really really shouldn't need unsafe, it's a better choice.

@alice-i-cecile alice-i-cecile added the S-Blocked This cannot move forward until something else changes label Mar 26, 2024
@alice-i-cecile
Copy link
Member

Merging is blocked on #12728

@james7132 james7132 removed the S-Blocked This cannot move forward until something else changes label Mar 27, 2024
@james7132
Copy link
Member Author

Allowing it for now and using #12743 to address the soundness issues.

@james7132 james7132 added this pull request to the merge queue Mar 27, 2024
Merged via the queue into bevyengine:main with commit 56bcbb0 Mar 27, 2024
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Cross-Cutting Impacts the entire engine C-Code-Quality A section of code that is hard to understand or change P-Unsound A bug that results in undefined compiler behavior S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Deny unsafe code in most of the code base
5 participants