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

Clean up pointer use in BundleSpawner/BundleInserter #12269

Merged
merged 9 commits into from
Mar 6, 2024

Conversation

james7132
Copy link
Member

@james7132 james7132 commented Mar 3, 2024

Objective

Following #10756, we're now using raw pointers in BundleInserter and BundleSpawner. This is primarily to get around the need to split the borrow on the World, but it leaves a lot to be desired in terms of safety guarantees. There's no type level guarantee the code can't dereference a null pointer, and it's restoring them to borrows fairly liberally within the associated functions.

Solution

  • Replace the pointers with NonNull and a new bevy_ptr::ConstNonNull that only allows conversion back to read-only borrows
  • Remove the closure to avoid potentially aliasing through the closure by restructuring the match expression.
  • Move all conversions back into borrows as far up as possible to ensure that the borrow checker is at least locally followed.

@james7132 james7132 added A-ECS Entities, components, systems, and events C-Code-Quality A section of code that is hard to understand or change P-Unsound A bug that results in undefined compiler behavior labels Mar 3, 2024
Copy link
Contributor

github-actions bot commented Mar 3, 2024

You added a new example but didn't add metadata for it. Please update the root Cargo.toml file.

Copy link
Contributor

@james-j-obrien james-j-obrien left a comment

Choose a reason for hiding this comment

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

Looks reasonable to me.

@alice-i-cecile alice-i-cecile added this to the 0.14 milestone Mar 3, 2024
Copy link
Member

@JoJoJet JoJoJet left a comment

Choose a reason for hiding this comment

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

Definitely seems like an improvement

I wonder if it would make more sense for bevy_ptr's non-null API to look more like a typed version of bevy_ptr::Ptr

pub struct NonNull<'a, T> {
    ptr: NonNull<T>,
    _ref: PhantomData<&'a T>,
}
pub struct NonNullMut<'a, T> {
    ptr: NonNull<T>,
    _ref: PhantomData<&'a mut T>,
}

This should allow us to enforce at compile time that the data is initialized and aligned and valid for reads/writes, so to dereference it you'd just need to guarantee there's no aliasing

@james7132
Copy link
Member Author

james7132 commented Mar 4, 2024

I wonder if it would make more sense for bevy_ptr's non-null API to look more like a typed version of bevy_ptr::Ptr

Isn't that just &'a T and &'a mut T? The way I view it is that borrows are lifetimed, mutability-locked, aligned, and strongly typed pointers, and bevy_ptr tries to fill the gap between *mut () and &'a T by dropping one or more of the constraints on borrows.

@james7132 james7132 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 4, 2024
@JoJoJet
Copy link
Member

JoJoJet commented Mar 4, 2024

Isn't that just &'a T and &'a mut T?

I see it as an &'a mut T with the aliasing requirement lifted -- but I guess that's just &'a UnsafeCell<T>

crates/bevy_ptr/src/lib.rs Outdated Show resolved Hide resolved
@james7132 james7132 enabled auto-merge March 6, 2024 04:38
@alice-i-cecile alice-i-cecile disabled auto-merge March 6, 2024 04:41
@alice-i-cecile
Copy link
Member

CI is failing still <3

@james7132 james7132 added this pull request to the merge queue Mar 6, 2024
Merged via the queue into bevyengine:main with commit 4cd53cc Mar 6, 2024
25 checks passed
spectria-limina pushed a commit to spectria-limina/bevy that referenced this pull request Mar 9, 2024
# Objective
Following bevyengine#10756, we're now using raw pointers in BundleInserter and
BundleSpawner. This is primarily to get around the need to split the
borrow on the World, but it leaves a lot to be desired in terms of
safety guarantees. There's no type level guarantee the code can't
dereference a null pointer, and it's restoring them to borrows fairly
liberally within the associated functions.

## Solution

* Replace the pointers with `NonNull` and a new `bevy_ptr::ConstNonNull`
that only allows conversion back to read-only borrows
* Remove the closure to avoid potentially aliasing through the closure
by restructuring the match expression.
* Move all conversions back into borrows as far up as possible to ensure
that the borrow checker is at least locally followed.
@james7132 james7132 deleted the cleanup-bundles branch March 10, 2024 07:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-ECS Entities, components, systems, and events 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.

5 participants