-
-
Notifications
You must be signed in to change notification settings - Fork 3.5k
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
Add core
and alloc
over std
Lints
#15281
base: main
Are you sure you want to change the base?
Conversation
Your PR increases Bevy Minimum Supported Rust Version. Please update the |
Cannot rely on call-sites having `extern crate alloc;`. Perhaps `bevy_ecs` could re-export `Box` for this macro, but `std` is fine for now.
I think we should do this. This is easy to enforce and for contributors to adapt to, and the auto-fix is particularly nice. Import consistency is a nice side benefit too. I'm not convinced that Bevy will ever be able to be fully no-std, but doing this now will make supporting weird platforms (notably consoles) in the future much easier and give us a better sense of how far away we are, what changes we need upstream and what parts of the standard library the teams will need to reimplement for their platform. |
We wish to use different lints for the examples, and `cargo` currently doesn't support overriding workspace lints within a crate. As a workaround, all workspace lints are duplicated for the root crate to allow it to specifically allow the standard library.
To avoid changes to the examples, I've had to duplicate the workspace lints in the root |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Below are some comments for reviewers which may help with parsing such a large set of changes. I believe this highlights all the noteworthy classes of changes that are made in this PR.
Cargo.toml
Outdated
rust-version = "1.79.0" | ||
rust-version = "1.81.0" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Required for core::error::Error
std_instead_of_core = "warn" | ||
std_instead_of_alloc = "warn" | ||
alloc_instead_of_core = "warn" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These lints direct Bevy contributors to use core
where possible, then alloc
, and then finally std
. The status quo is to just import everything from std
. Enabling these lints makes investigation into a no_std
Bevy feasible. Additionally, items in alloc
and std
but not in core
can indicate blocking or allocating types, which could impact performance.
[lints] | ||
workspace = true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We explicitly don't want examples to be subject to the same linting requirements as the rest of Bevy, since it is encouraged that users rely on the Rust std
library when possible. Unfortunately, there is no way to override just those lints, so a copy of the workspace lints is needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add a comment to this effect here and in the workspace lints to reduce the risk of desync.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!
format!("{}_entities_{}", entity_count, std::any::type_name::<T>()), | ||
format!("{}_entities_{}", entity_count, core::any::type_name::<T>()), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most changes look like this, where some inline call to a std
item needs to be replaced with the core
/alloc
alternative. As std
re-exports alloc
and core
, this is a non-breaking change even in public facing signatures.
use std::sync::{ | ||
atomic::{AtomicBool, Ordering}, | ||
Arc, | ||
}; | ||
extern crate alloc; | ||
|
||
use alloc::sync::Arc; | ||
use core::sync::atomic::{AtomicBool, Ordering}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In cases where the alloc
crate is required, an extern crate alloc;
must be placed in the lib.rs
/main.rs
file at the crate root. It may be possible to remove these if we instead created a bevy_alloc
crate, and depend on it for the alloc
types. This may be desirable anyway, as it would be a more appropriate home for things like HashMap
and EntityHashSet
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather us just follow convention instead of establishing our own patterns. This seems like a rather non-intrusive requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, and there's definitely a benefit to keeping it explicit and simple, especially considering this feature is aimed at the more low-level side of Rust programming.
impl #impl_generics ::std::ops::Deref for #ident #ty_generics #where_clause { | ||
impl #impl_generics ::core::ops::Deref for #ident #ty_generics #where_clause { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Care needs to be taken with these macros, as we can rely on the existence of core
, but we can't rely on the existence of alloc
, as the callsite needs to already have extern crate alloc;
added. Again, this would be addressed by providing a bevy_alloc
crate, giving a concrete FQN that we can always rely on.
@@ -6,6 +6,8 @@ | |||
//! To demonstrate change detection, there are some console outputs based on changes in | |||
//! the `EntityCounter` resource and updated Age components | |||
|
|||
#![expect(clippy::std_instead_of_core)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These examples require this expect
attribute because they are inside the bevy_ecs
crate and thus subject to the workspace lints. It's not ideal, but there are only a couple of cases where this is required.
// Re-exported for use within `define_label!` | ||
#[doc(hidden)] | ||
pub use alloc::boxed::Box; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is required for the define_label!
macro. It's definitely not ideal, and I'd like to move it to a dedicated bevy_alloc
crate instead, but it's a minimal issue IMO.
use bevy::math::ops; | ||
use bevy::prelude::*; | ||
use bevy::{math::ops, prelude::*}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Examples have just had minor formatting changes made to their use
statements based on cargo +nightly fmt
. They are exempt from the lint requiring core
and alloc
where possible.
Explains the requirement for duplicating the lints as a form of workspace overrides
Co-Authored-By: François Mockers <francois.mockers@vleue.com>
Co-Authored-By: François Mockers <francois.mockers@vleue.com>
Co-Authored-By: François Mockers <francois.mockers@vleue.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only have looked through half the the files so far, but so far LGTM.
use std::sync::{ | ||
atomic::{AtomicBool, Ordering}, | ||
Arc, | ||
}; | ||
extern crate alloc; | ||
|
||
use alloc::sync::Arc; | ||
use core::sync::atomic::{AtomicBool, Ordering}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather us just follow convention instead of establishing our own patterns. This seems like a rather non-intrusive requirement.
However, `bevy_ptr` and `bevy_utils` must still link to `core` and `alloc` due to the possibility of being `no_std` based on feature gating.
Objective
core
andalloc
overstd
where possible #6370Solution
std_instead_of_core
std_instead_of_alloc
alloc_instead_of_core
cargo +nightly fmt
with item level use formatting to split alluse
statements into single items.cargo clippy --workspace --all-targets --all-features --fix --allow-dirty
to attempt to resolve the new linting issues, and intervened where the lint was unable to resolve the issue automatically (usually due to needing anextern crate alloc;
statement in a crate root).std
where negative feature gating prevented--all-features
from finding the offending uses.cargo +nightly fmt
with crate level use formatting to re-merge alluse
statements matching Bevy's previous styling.fmt
tool could not re-mergeuse
statements due to conditional compilation attributes.Testing
Migration Guide
The MSRV is now 1.81. Please update to this version or higher.
Notes
core
andalloc
instead ofstd
where possible.no_std
options for Bevy.