# Objective - Improve error descriptions and help understand how to fix them - I noticed one today that could be expanded, it seemed like a good starting point ## Solution - Start something like https://github.com/rust-lang/rust/tree/master/compiler/rustc_error_codes/src/error_codes - Remove sentence about Rust mutability rules which is not very helpful in the error message I decided to start the error code with B for Bevy so that they're not confused with error code from rust (which starts with E) Longer term, there are a few more evolutions that can continue this: - the code samples should be compiled check, and even executed for some of them to check they have the correct error code in a panic - the error could be build on a page in the website like https://doc.rust-lang.org/error-index.html - most panic should have their own error code
2.3 KiB
B0001
To keep Rust rules on references (either one mutable reference or any number of immutable references) on a component, it is not possible to have two queries on the same component when one request mutable access to it in the same system.
Erroneous code example:
use bevy::prelude::*;
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Enemy;
fn move_enemies_to_player(
mut enemies: Query<&mut Transform, With<Enemy>>,
player: Query<&Transform, With<Player>>,
) {
// ...
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_system(move_enemies_to_player)
.run();
}
This will panic, as it's not possible to have both a mutable and an immutable query on Transform
at the same time.
You have two solutions:
Solution #1: use disjoint queries using Without
As a Player
entity won't be an Enemy
at the same time, those two queries will acutally never target the same entity. This can be encoded in the query filter with Without
:
use bevy::prelude::*;
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Enemy;
fn move_enemies_to_player(
mut enemies: Query<&mut Transform, With<Enemy>>,
player: Query<&Transform, (With<Player>, Without<Enemy>)>,
) {
// ...
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_system(move_enemies_to_player)
.run();
}
Solution #2: use a QuerySet
A QuerySet
will let you have conflicting queries as a parameter, but you will still be responsible of not using them at the same time in your system.
use bevy::prelude::*;
#[derive(Component)]
struct Player;
#[derive(Component)]
struct Enemy;
fn move_enemies_to_player(
mut transforms: QuerySet<(
QueryState<&mut Transform, With<Enemy>>,
QueryState<&Transform, With<Player>>,
)>,
) {
// ...
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_system(move_enemies_to_player)
.run();
}