mirror of
https://github.com/bevyengine/bevy
synced 2024-11-29 08:00:20 +00:00
Switch to ui_test in compile fail tests. (#12810)
# Objective Make compile fail tests less likely to break with new Rust versions. Closes #12627 ## Solution Switch from [`trybuild`](https://github.com/dtolnay/trybuild) to [`ui_test`](https://github.com/oli-obk/ui_test). ## TODO - [x] Update `bevy_ecs_compile_fail_tests` - [x] Update `bevy_macros_compile_fail_tests` - [x] Update `bevy_reflect_compile_fail_tests` --------- Co-authored-by: Oli Scherer <github35764891676564198441@oli-obk.de> Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
This commit is contained in:
parent
de9dc9c204
commit
9d59e52bb0
107 changed files with 896 additions and 427 deletions
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
|
@ -52,5 +52,5 @@ jobs:
|
||||||
base: "main"
|
base: "main"
|
||||||
title: "Preparing Next Release"
|
title: "Preparing Next Release"
|
||||||
body: |
|
body: |
|
||||||
Preparing next release
|
Preparing next release. This PR has been auto-generated.
|
||||||
This PR has been auto-generated
|
UI tests have not been automatically bumped to the latest version, please fix them manually.
|
||||||
|
|
|
@ -19,6 +19,7 @@ exclude = [
|
||||||
"crates/bevy_ecs_compile_fail_tests",
|
"crates/bevy_ecs_compile_fail_tests",
|
||||||
"crates/bevy_macros_compile_fail_tests",
|
"crates/bevy_macros_compile_fail_tests",
|
||||||
"crates/bevy_reflect_compile_fail_tests",
|
"crates/bevy_reflect_compile_fail_tests",
|
||||||
|
"crates/bevy_compile_test_utils",
|
||||||
]
|
]
|
||||||
members = [
|
members = [
|
||||||
"crates/*",
|
"crates/*",
|
||||||
|
|
15
crates/bevy_compile_test_utils/Cargo.toml
Normal file
15
crates/bevy_compile_test_utils/Cargo.toml
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
[package]
|
||||||
|
name = "bevy_compile_test_utils"
|
||||||
|
edition = "2021"
|
||||||
|
description = "Utils for compile tests used in the engine"
|
||||||
|
homepage = "https://bevyengine.org"
|
||||||
|
repository = "https://github.com/bevyengine/bevy"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ui_test = "0.22.3"
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "example"
|
||||||
|
harness = false
|
44
crates/bevy_compile_test_utils/README.md
Normal file
44
crates/bevy_compile_test_utils/README.md
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
# Helpers for compile fail tests
|
||||||
|
|
||||||
|
This crate contains everything needed to set up compile tests for the Bevy repo. It, like all Bevy compile test crates, is excluded from the Bevy workspace. This is done to not fail [`crater` tests](https://github.com/rust-lang/crater) for Bevy. The `CI` workflow executes these tests on the stable rust toolchain see ([tools/ci](../../tools/ci/src/main.rs)).
|
||||||
|
|
||||||
|
## Writing new test cases
|
||||||
|
|
||||||
|
Test cases are annotated .rs files. These annotations define how the test case should be run and what we're expecting to fail. Please see <https://github.com/oli-obk/ui_test/blob/main/README.md> for more information.
|
||||||
|
|
||||||
|
Annotations can roughly be split into global annotations which are prefixed with `//@` and define how tests should be run and error annotations which are prefixed with `//~` and define where errors we expect to happen. From the global annotations, you're only likely to care about `//@check-pass` which will make any compile errors in the test trigger a test failure.
|
||||||
|
|
||||||
|
The error annotations are composed of two parts.
|
||||||
|
An optional location specifier:
|
||||||
|
|
||||||
|
- `^` The error happens on the line above.
|
||||||
|
- `v` The error happens on the line below.
|
||||||
|
- `|` The error annotation is connected to another one.
|
||||||
|
- If the location specifier is missing, the error is assumed to happen on the same line as the annotation.
|
||||||
|
|
||||||
|
An error matcher:
|
||||||
|
|
||||||
|
- `E####` The error we're expecting has the [`####` rustc error code](https://doc.rust-lang.org/error_codes/error-index.html), e.g `E0499`
|
||||||
|
- `<lint_name>` The given [compiler lint](https://doc.rust-lang.org/rustc/lints/index.html) is triggered, e.g. `dead_code`
|
||||||
|
- `LEVEL: <substring>` A compiler error of the given level (valid levels are: `ERROR`, `HELP`, `WARN` or `NOTE`) will be raised and it will contain the `substring`. Substrings can contain spaces.
|
||||||
|
- `LEVEL: /<regex>/` Same as above but a regex is used to match the error message.
|
||||||
|
|
||||||
|
An example of an error annotation would be `//~v ERROR: missing trait`. This error annotation will match any error occurring on the line below that contains the substring `missing trait`.
|
||||||
|
|
||||||
|
## Adding compile fail tests for a crate that doesn't have them
|
||||||
|
|
||||||
|
This will be a rather involved process. You'll have to:
|
||||||
|
|
||||||
|
- Create an empty library crate in the [`crates`](..) directory.
|
||||||
|
- Add this crate as a `dev-dependency`.
|
||||||
|
- Create a folder called `tests` within the new crate.
|
||||||
|
- Add a test runner file to this folder. The file should contain a main function calling one of the test functions defined in this crate.
|
||||||
|
- Add a `[[test]]` table to the `Cargo.toml`. This table will need to contain `harness = false` and `name = <name of the test runner file you defined>`.
|
||||||
|
- Modify the [`Ci`](../../tools/ci/) tool to run `cargo test` on this crate.
|
||||||
|
- And finally, write your compile tests.
|
||||||
|
|
||||||
|
If you have any questions, don't be scared to ask for help.
|
||||||
|
|
||||||
|
## A note about `.stderr` files
|
||||||
|
|
||||||
|
We're capable of generating `.stderr` files for all our compile tests. These files contain the error output generated by the test. To create or regenerate them yourself, trigger the tests with the `BLESS` environment variable set to any value (e.g. `BLESS="some symbolic value"`). We currently have to ignore mismatches between these files and the actual stderr output from their corresponding test due to issues with file paths. We attempt to sanitize file paths but for proc-macros, the compiler error messages contain file paths to the current toolchain's copy of the standard library. If we knew of a way to construct a path to the current toolchains folder we could fix this.
|
101
crates/bevy_compile_test_utils/src/lib.rs
Normal file
101
crates/bevy_compile_test_utils/src/lib.rs
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
use std::{
|
||||||
|
env,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
// Re-export ui_test so all the tests use the same version.
|
||||||
|
pub use ui_test;
|
||||||
|
|
||||||
|
use ui_test::{
|
||||||
|
default_file_filter, default_per_file_config, run_tests_generic,
|
||||||
|
status_emitter::{Gha, StatusEmitter, Text},
|
||||||
|
Args, Config, OutputConflictHandling,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Use this instead of hand rolling configs.
|
||||||
|
///
|
||||||
|
/// `root_dir` is the directory your tests are contained in. Needs to be a path from crate root.
|
||||||
|
fn basic_config(root_dir: impl Into<PathBuf>, args: &Args) -> Config {
|
||||||
|
let mut config = Config {
|
||||||
|
dependencies_crate_manifest_path: Some("Cargo.toml".into()),
|
||||||
|
bless_command: Some("`cargo test` with the BLESS environment variable set to any non empty value".to_string()),
|
||||||
|
output_conflict_handling: if env::var_os("BLESS").is_some() {
|
||||||
|
OutputConflictHandling::Bless
|
||||||
|
} else {
|
||||||
|
// stderr output changes between rust versions so we just rely on annotations
|
||||||
|
OutputConflictHandling::Ignore
|
||||||
|
},
|
||||||
|
..Config::rustc(root_dir)
|
||||||
|
};
|
||||||
|
|
||||||
|
config.with_args(args);
|
||||||
|
|
||||||
|
let bevy_root = "..";
|
||||||
|
|
||||||
|
// Don't leak contributor filesystem paths
|
||||||
|
config.path_stderr_filter(Path::new(bevy_root), b"$BEVY_ROOT");
|
||||||
|
config.path_stderr_filter(Path::new(env!("RUSTUP_HOME")), b"$RUSTUP_HOME");
|
||||||
|
|
||||||
|
// ui_test doesn't compile regex with perl character classes.
|
||||||
|
// \pL = unicode class for letters, \pN = unicode class for numbers
|
||||||
|
config.stderr_filter(r"\/home\/[\pL\pN_@#\-\. ]+", "$HOME");
|
||||||
|
// Paths in .stderr seem to always be normalized to use /. Handle both anyway.
|
||||||
|
config.stderr_filter(
|
||||||
|
r"[a-zA-Z]:(?:\\|\/)users(?:\\|\/)[\pL\pN_@#\-\. ]+", // NOTE: [\pL\pN_@#\-\. ] is a poor attempt at handling usernames
|
||||||
|
"$HOME",
|
||||||
|
);
|
||||||
|
|
||||||
|
config
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs ui tests for a single directory.
|
||||||
|
///
|
||||||
|
/// `root_dir` is the directory your tests are contained in. Needs to be a path from crate root.
|
||||||
|
pub fn test(test_root: impl Into<PathBuf>) -> ui_test::Result<()> {
|
||||||
|
test_multiple([test_root])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run ui tests with the given config
|
||||||
|
pub fn test_with_config(config: Config) -> ui_test::Result<()> {
|
||||||
|
test_with_multiple_configs([config])
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs ui tests for a multiple directories.
|
||||||
|
///
|
||||||
|
/// `root_dirs` paths need to come from crate root.
|
||||||
|
pub fn test_multiple(
|
||||||
|
test_roots: impl IntoIterator<Item = impl Into<PathBuf>>,
|
||||||
|
) -> ui_test::Result<()> {
|
||||||
|
let args = Args::test()?;
|
||||||
|
|
||||||
|
let configs = test_roots.into_iter().map(|root| basic_config(root, &args));
|
||||||
|
|
||||||
|
test_with_multiple_configs(configs)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Run ui test with the given configs.
|
||||||
|
///
|
||||||
|
/// Tests for configs are run in parallel.
|
||||||
|
pub fn test_with_multiple_configs(
|
||||||
|
configs: impl IntoIterator<Item = Config>,
|
||||||
|
) -> ui_test::Result<()> {
|
||||||
|
let configs = configs.into_iter().collect();
|
||||||
|
|
||||||
|
let emitter: Box<dyn StatusEmitter + Send> = if env::var_os("CI").is_some() {
|
||||||
|
Box::new((
|
||||||
|
Text::verbose(),
|
||||||
|
Gha::<true> {
|
||||||
|
name: env!("CARGO_PKG_NAME").to_string(),
|
||||||
|
},
|
||||||
|
))
|
||||||
|
} else {
|
||||||
|
Box::new(Text::quiet())
|
||||||
|
};
|
||||||
|
|
||||||
|
run_tests_generic(
|
||||||
|
configs,
|
||||||
|
default_file_filter,
|
||||||
|
default_per_file_config,
|
||||||
|
emitter,
|
||||||
|
)
|
||||||
|
}
|
10
crates/bevy_compile_test_utils/tests/example.rs
Normal file
10
crates/bevy_compile_test_utils/tests/example.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
fn main() -> bevy_compile_test_utils::ui_test::Result<()> {
|
||||||
|
// Run all tests in the tests/example_tests folder.
|
||||||
|
// If we had more tests we could either call this function
|
||||||
|
// on everysingle one or use test_multiple and past it an array
|
||||||
|
// of paths.
|
||||||
|
//
|
||||||
|
// Don't forget that when running tests the working directory
|
||||||
|
// is set to the crate root.
|
||||||
|
bevy_compile_test_utils::test("tests/example_tests")
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Compiler warnings also need to be annotated. We don't
|
||||||
|
// want to annotate all the unused variables so let's instruct
|
||||||
|
// the compiler to ignore them.
|
||||||
|
#![allow(unused_variables)]
|
||||||
|
|
||||||
|
fn bad_moves() {
|
||||||
|
let x = String::new();
|
||||||
|
// Help diagnostics need to be annotated
|
||||||
|
let y = x;
|
||||||
|
//~^ HELP: consider cloning
|
||||||
|
|
||||||
|
// We expect a failure on this line
|
||||||
|
println!("{x}"); //~ ERROR: borrow
|
||||||
|
|
||||||
|
|
||||||
|
let x = String::new();
|
||||||
|
// We expect the help message to mention cloning.
|
||||||
|
//~v HELP: consider cloning
|
||||||
|
let y = x;
|
||||||
|
|
||||||
|
// Check error message using a regex
|
||||||
|
println!("{x}");
|
||||||
|
//~^ ERROR: /(move)|(borrow)/
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
error[E0382]: borrow of moved value: `x`
|
||||||
|
--> tests/example_tests/basic_test.rs:13:15
|
||||||
|
|
|
||||||
|
7 | let x = String::new();
|
||||||
|
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
|
||||||
|
8 | // Help diagnostics need to be annotated
|
||||||
|
9 | let y = x;
|
||||||
|
| - value moved here
|
||||||
|
...
|
||||||
|
13 | println!("{x}");
|
||||||
|
| ^^^ value borrowed here after move
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
||||||
|
9 | let y = x.clone();
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error[E0382]: borrow of moved value: `x`
|
||||||
|
--> tests/example_tests/basic_test.rs:22:15
|
||||||
|
|
|
||||||
|
16 | let x = String::new();
|
||||||
|
| - move occurs because `x` has type `String`, which does not implement the `Copy` trait
|
||||||
|
...
|
||||||
|
19 | let y = x;
|
||||||
|
| - value moved here
|
||||||
|
...
|
||||||
|
22 | println!("{x}");
|
||||||
|
| ^^^ value borrowed here after move
|
||||||
|
|
|
||||||
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
help: consider cloning the value if the performance cost is acceptable
|
||||||
|
|
|
||||||
|
19 | let y = x.clone();
|
||||||
|
| ++++++++
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0382`.
|
|
@ -0,0 +1,7 @@
|
||||||
|
// You can import anything defined in the dependencies table of the crate.
|
||||||
|
use ui_test::Config;
|
||||||
|
|
||||||
|
fn wrong_type() {
|
||||||
|
let _ = Config::this_function_does_not_exist();
|
||||||
|
//~^ E0599
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
error[E0599]: no function or associated item named `this_function_does_not_exist` found for struct `Config` in the current scope
|
||||||
|
--> tests/example_tests/import.rs:5:21
|
||||||
|
|
|
||||||
|
5 | let _ = Config::this_function_does_not_exist();
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `Config`
|
||||||
|
|
|
||||||
|
note: if you're trying to build a new `Config` consider using one of the following associated functions:
|
||||||
|
Config::rustc
|
||||||
|
Config::cargo
|
||||||
|
--> $RUSTUP_HOME/.cargo/git/checkouts/ui_test-2b82183a391bb05c/680bb08/src/config.rs:63:5
|
||||||
|
|
|
||||||
|
63 | pub fn rustc(root_dir: impl Into<PathBuf>) -> Self {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
...
|
||||||
|
108 | pub fn cargo(root_dir: impl Into<PathBuf>) -> Self {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0599`.
|
|
@ -0,0 +1,10 @@
|
||||||
|
//@check-pass
|
||||||
|
|
||||||
|
// This code is expected to compile correctly.
|
||||||
|
fn correct_borrowing() {
|
||||||
|
let x = String::new();
|
||||||
|
let y = &x;
|
||||||
|
|
||||||
|
println!("{x}");
|
||||||
|
println!("{y}");
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
warning: function `correct_borrowing` is never used
|
||||||
|
--> tests/example_tests/pass_test.rs:4:4
|
||||||
|
|
|
||||||
|
4 | fn correct_borrowing() {
|
||||||
|
| ^^^^^^^^^^^^^^^^^
|
||||||
|
|
|
||||||
|
= note: `#[warn(dead_code)]` on by default
|
||||||
|
|
||||||
|
warning: 1 warning emitted
|
||||||
|
|
|
@ -7,6 +7,13 @@ repository = "https://github.com/bevyengine/bevy"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# ui_test dies if we don't specify the version. See oli-obk/ui_test#211
|
||||||
|
bevy_ecs = { path = "../bevy_ecs", version = "0.14.0-dev" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy_ecs = { path = "../bevy_ecs" }
|
bevy_compile_test_utils = { path = "../bevy_compile_test_utils" }
|
||||||
trybuild = "1.0.71"
|
|
||||||
|
[[test]]
|
||||||
|
name = "ui"
|
||||||
|
harness = false
|
||||||
|
|
|
@ -3,3 +3,5 @@
|
||||||
This crate is separate from `bevy_ecs` and not part of the Bevy workspace in order to not fail `crater` tests for Bevy. The tests assert on the exact compiler errors and can easily fail for new Rust versions due to updated compiler errors (e.g. changes in spans).
|
This crate is separate from `bevy_ecs` and not part of the Bevy workspace in order to not fail `crater` tests for Bevy. The tests assert on the exact compiler errors and can easily fail for new Rust versions due to updated compiler errors (e.g. changes in spans).
|
||||||
|
|
||||||
The `CI` workflow executes these tests on the stable rust toolchain (see [tools/ci](../../tools/ci/src/main.rs)).
|
The `CI` workflow executes these tests on the stable rust toolchain (see [tools/ci](../../tools/ci/src/main.rs)).
|
||||||
|
|
||||||
|
For information on writing tests see [bevy_compile_test_utils/README.md](../bevy_compile_test_utils/README.md).
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
#[test]
|
fn main() -> bevy_compile_test_utils::ui_test::Result<()> {
|
||||||
fn test() {
|
bevy_compile_test_utils::test("tests/ui")
|
||||||
let t = trybuild::TestCases::new();
|
|
||||||
t.compile_fail("tests/ui/*.rs");
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@ fn main() {
|
||||||
{
|
{
|
||||||
let gotten: &A = e_mut.get::<A>().unwrap();
|
let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
let gotten2: A = e_mut.take::<A>().unwrap();
|
let gotten2: A = e_mut.take::<A>().unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(gotten, &gotten2); // oops UB
|
assert_eq!(gotten, &gotten2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +24,7 @@ fn main() {
|
||||||
{
|
{
|
||||||
let mut gotten: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
let mut gotten: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
||||||
let mut gotten2: A = e_mut.take::<A>().unwrap();
|
let mut gotten2: A = e_mut.take::<A>().unwrap();
|
||||||
|
//~^ E0499
|
||||||
assert_eq!(&mut *gotten, &mut gotten2); // oops UB
|
assert_eq!(&mut *gotten, &mut gotten2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,6 +33,7 @@ fn main() {
|
||||||
{
|
{
|
||||||
let gotten: &A = e_mut.get::<A>().unwrap();
|
let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
e_mut.despawn();
|
e_mut.despawn();
|
||||||
|
//~^ E0505
|
||||||
assert_eq!(gotten, &A(Box::new(14_usize))); // oops UB
|
assert_eq!(gotten, &A(Box::new(14_usize))); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,18 +43,21 @@ fn main() {
|
||||||
{
|
{
|
||||||
let gotten: &A = e_mut.get::<A>().unwrap();
|
let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
let gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
let gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(gotten, &*gotten_mut); // oops UB
|
assert_eq!(gotten, &*gotten_mut); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
let gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
||||||
let gotten: &A = e_mut.get::<A>().unwrap();
|
let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(gotten, &*gotten_mut); // oops UB
|
assert_eq!(gotten, &*gotten_mut); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let gotten: &A = e_mut.get::<A>().unwrap();
|
let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
e_mut.insert::<B>(B);
|
e_mut.insert::<B>(B);
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(gotten, &A(Box::new(16_usize))); // oops UB
|
assert_eq!(gotten, &A(Box::new(16_usize))); // oops UB
|
||||||
e_mut.remove::<B>();
|
e_mut.remove::<B>();
|
||||||
}
|
}
|
||||||
|
@ -59,6 +65,7 @@ fn main() {
|
||||||
{
|
{
|
||||||
let mut gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
let mut gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
||||||
e_mut.insert::<B>(B);
|
e_mut.insert::<B>(B);
|
||||||
|
//~^ E0499
|
||||||
assert_eq!(&mut *gotten_mut, &mut A(Box::new(16_usize))); // oops UB
|
assert_eq!(&mut *gotten_mut, &mut A(Box::new(16_usize))); // oops UB
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,68 +5,80 @@ error[E0502]: cannot borrow `e_mut` as mutable because it is also borrowed as im
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
17 | let gotten2: A = e_mut.take::<A>().unwrap();
|
17 | let gotten2: A = e_mut.take::<A>().unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
18 | assert_eq!(gotten, &gotten2); // oops UB
|
18 |
|
||||||
|
19 | assert_eq!(gotten, &gotten2); // oops UB
|
||||||
| ---------------------------- immutable borrow later used here
|
| ---------------------------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow `e_mut` as mutable more than once at a time
|
error[E0499]: cannot borrow `e_mut` as mutable more than once at a time
|
||||||
--> tests/ui/entity_ref_mut_lifetime_safety.rs:25:30
|
--> tests/ui/entity_ref_mut_lifetime_safety.rs:26:30
|
||||||
|
|
|
|
||||||
24 | let mut gotten: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
25 | let mut gotten: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
||||||
| ----- first mutable borrow occurs here
|
| ----- first mutable borrow occurs here
|
||||||
25 | let mut gotten2: A = e_mut.take::<A>().unwrap();
|
26 | let mut gotten2: A = e_mut.take::<A>().unwrap();
|
||||||
| ^^^^^ second mutable borrow occurs here
|
| ^^^^^ second mutable borrow occurs here
|
||||||
26 | assert_eq!(&mut *gotten, &mut gotten2); // oops UB
|
27 |
|
||||||
|
28 | assert_eq!(&mut *gotten, &mut gotten2); // oops UB
|
||||||
| ------ first borrow later used here
|
| ------ first borrow later used here
|
||||||
|
|
||||||
error[E0505]: cannot move out of `e_mut` because it is borrowed
|
error[E0505]: cannot move out of `e_mut` because it is borrowed
|
||||||
--> tests/ui/entity_ref_mut_lifetime_safety.rs:33:9
|
--> tests/ui/entity_ref_mut_lifetime_safety.rs:35:9
|
||||||
|
|
|
|
||||||
13 | let mut e_mut = world.entity_mut(e);
|
13 | let mut e_mut = world.entity_mut(e);
|
||||||
| --------- binding `e_mut` declared here
|
| --------- binding `e_mut` declared here
|
||||||
...
|
...
|
||||||
32 | let gotten: &A = e_mut.get::<A>().unwrap();
|
34 | let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
| ----- borrow of `e_mut` occurs here
|
| ----- borrow of `e_mut` occurs here
|
||||||
33 | e_mut.despawn();
|
35 | e_mut.despawn();
|
||||||
| ^^^^^ move out of `e_mut` occurs here
|
| ^^^^^ move out of `e_mut` occurs here
|
||||||
34 | assert_eq!(gotten, &A(Box::new(14_usize))); // oops UB
|
36 |
|
||||||
|
37 | assert_eq!(gotten, &A(Box::new(14_usize))); // oops UB
|
||||||
| ------------------------------------------ borrow later used here
|
| ------------------------------------------ borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `e_mut` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `e_mut` as mutable because it is also borrowed as immutable
|
||||||
--> tests/ui/entity_ref_mut_lifetime_safety.rs:42:34
|
--> tests/ui/entity_ref_mut_lifetime_safety.rs:45:34
|
||||||
|
|
|
|
||||||
41 | let gotten: &A = e_mut.get::<A>().unwrap();
|
44 | let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
42 | let gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
45 | let gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
43 | assert_eq!(gotten, &*gotten_mut); // oops UB
|
46 |
|
||||||
|
47 | assert_eq!(gotten, &*gotten_mut); // oops UB
|
||||||
| -------------------------------- immutable borrow later used here
|
| -------------------------------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `e_mut` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `e_mut` as immutable because it is also borrowed as mutable
|
||||||
--> tests/ui/entity_ref_mut_lifetime_safety.rs:48:26
|
--> tests/ui/entity_ref_mut_lifetime_safety.rs:52:26
|
||||||
|
|
|
|
||||||
47 | let gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
51 | let gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
||||||
| ----- mutable borrow occurs here
|
| ----- mutable borrow occurs here
|
||||||
48 | let gotten: &A = e_mut.get::<A>().unwrap();
|
52 | let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
| ^^^^^ immutable borrow occurs here
|
| ^^^^^ immutable borrow occurs here
|
||||||
49 | assert_eq!(gotten, &*gotten_mut); // oops UB
|
53 |
|
||||||
|
54 | assert_eq!(gotten, &*gotten_mut); // oops UB
|
||||||
| ---------- mutable borrow later used here
|
| ---------- mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `e_mut` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `e_mut` as mutable because it is also borrowed as immutable
|
||||||
--> tests/ui/entity_ref_mut_lifetime_safety.rs:54:9
|
--> tests/ui/entity_ref_mut_lifetime_safety.rs:59:9
|
||||||
|
|
|
|
||||||
53 | let gotten: &A = e_mut.get::<A>().unwrap();
|
58 | let gotten: &A = e_mut.get::<A>().unwrap();
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
54 | e_mut.insert::<B>(B);
|
59 | e_mut.insert::<B>(B);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
55 | assert_eq!(gotten, &A(Box::new(16_usize))); // oops UB
|
60 |
|
||||||
|
61 | assert_eq!(gotten, &A(Box::new(16_usize))); // oops UB
|
||||||
| ------------------------------------------ immutable borrow later used here
|
| ------------------------------------------ immutable borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow `e_mut` as mutable more than once at a time
|
error[E0499]: cannot borrow `e_mut` as mutable more than once at a time
|
||||||
--> tests/ui/entity_ref_mut_lifetime_safety.rs:61:9
|
--> tests/ui/entity_ref_mut_lifetime_safety.rs:67:9
|
||||||
|
|
|
|
||||||
60 | let mut gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
66 | let mut gotten_mut: Mut<A> = e_mut.get_mut::<A>().unwrap();
|
||||||
| ----- first mutable borrow occurs here
|
| ----- first mutable borrow occurs here
|
||||||
61 | e_mut.insert::<B>(B);
|
67 | e_mut.insert::<B>(B);
|
||||||
| ^^^^^ second mutable borrow occurs here
|
| ^^^^^ second mutable borrow occurs here
|
||||||
62 | assert_eq!(&mut *gotten_mut, &mut A(Box::new(16_usize))); // oops UB
|
68 |
|
||||||
|
69 | assert_eq!(&mut *gotten_mut, &mut A(Box::new(16_usize))); // oops UB
|
||||||
| ---------- first borrow later used here
|
| ---------- first borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0499, E0502, E0505.
|
||||||
|
For more information about an error, try `rustc --explain E0499`.
|
||||||
|
|
|
@ -4,15 +4,13 @@ use bevy_ecs::prelude::*;
|
||||||
struct Foo;
|
struct Foo;
|
||||||
|
|
||||||
fn on_changed(query: Query<&Foo, Changed<Foo>>) {
|
fn on_changed(query: Query<&Foo, Changed<Foo>>) {
|
||||||
// this should fail to compile
|
|
||||||
is_exact_size_iterator(query.iter());
|
is_exact_size_iterator(query.iter());
|
||||||
|
//~^ E0277
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_added(query: Query<&Foo, Added<Foo>>) {
|
fn on_added(query: Query<&Foo, Added<Foo>>) {
|
||||||
// this should fail to compile
|
|
||||||
is_exact_size_iterator(query.iter());
|
is_exact_size_iterator(query.iter());
|
||||||
|
//~^ E0277
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_exact_size_iterator<T: ExactSizeIterator>(_iter: T) {}
|
fn is_exact_size_iterator<T: ExactSizeIterator>(_iter: T) {}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,7 +1,7 @@
|
||||||
error[E0277]: the trait bound `bevy_ecs::query::Changed<Foo>: ArchetypeFilter` is not satisfied
|
error[E0277]: the trait bound `bevy_ecs::query::Changed<Foo>: ArchetypeFilter` is not satisfied
|
||||||
--> tests/ui/query_exact_sized_iterator_safety.rs:8:28
|
--> tests/ui/query_exact_sized_iterator_safety.rs:7:28
|
||||||
|
|
|
|
||||||
8 | is_exact_size_iterator(query.iter());
|
7 | is_exact_size_iterator(query.iter());
|
||||||
| ---------------------- ^^^^^^^^^^^^ the trait `ArchetypeFilter` is not implemented for `bevy_ecs::query::Changed<Foo>`, which is required by `QueryIter<'_, '_, &Foo, bevy_ecs::query::Changed<Foo>>: ExactSizeIterator`
|
| ---------------------- ^^^^^^^^^^^^ the trait `ArchetypeFilter` is not implemented for `bevy_ecs::query::Changed<Foo>`, which is required by `QueryIter<'_, '_, &Foo, bevy_ecs::query::Changed<Foo>>: ExactSizeIterator`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
@ -15,7 +15,7 @@ error[E0277]: the trait bound `bevy_ecs::query::Changed<Foo>: ArchetypeFilter` i
|
||||||
Or<(F0, F1, F2)>
|
Or<(F0, F1, F2)>
|
||||||
Or<(F0, F1, F2, F3)>
|
Or<(F0, F1, F2, F3)>
|
||||||
Or<(F0, F1, F2, F3, F4)>
|
Or<(F0, F1, F2, F3, F4)>
|
||||||
and $N others
|
and 26 others
|
||||||
= note: required for `QueryIter<'_, '_, &Foo, bevy_ecs::query::Changed<Foo>>` to implement `ExactSizeIterator`
|
= note: required for `QueryIter<'_, '_, &Foo, bevy_ecs::query::Changed<Foo>>` to implement `ExactSizeIterator`
|
||||||
note: required by a bound in `is_exact_size_iterator`
|
note: required by a bound in `is_exact_size_iterator`
|
||||||
--> tests/ui/query_exact_sized_iterator_safety.rs:16:30
|
--> tests/ui/query_exact_sized_iterator_safety.rs:16:30
|
||||||
|
@ -24,9 +24,9 @@ note: required by a bound in `is_exact_size_iterator`
|
||||||
| ^^^^^^^^^^^^^^^^^ required by this bound in `is_exact_size_iterator`
|
| ^^^^^^^^^^^^^^^^^ required by this bound in `is_exact_size_iterator`
|
||||||
|
|
||||||
error[E0277]: the trait bound `bevy_ecs::query::Added<Foo>: ArchetypeFilter` is not satisfied
|
error[E0277]: the trait bound `bevy_ecs::query::Added<Foo>: ArchetypeFilter` is not satisfied
|
||||||
--> tests/ui/query_exact_sized_iterator_safety.rs:13:28
|
--> tests/ui/query_exact_sized_iterator_safety.rs:12:28
|
||||||
|
|
|
|
||||||
13 | is_exact_size_iterator(query.iter());
|
12 | is_exact_size_iterator(query.iter());
|
||||||
| ---------------------- ^^^^^^^^^^^^ the trait `ArchetypeFilter` is not implemented for `bevy_ecs::query::Added<Foo>`, which is required by `QueryIter<'_, '_, &Foo, bevy_ecs::query::Added<Foo>>: ExactSizeIterator`
|
| ---------------------- ^^^^^^^^^^^^ the trait `ArchetypeFilter` is not implemented for `bevy_ecs::query::Added<Foo>`, which is required by `QueryIter<'_, '_, &Foo, bevy_ecs::query::Added<Foo>>: ExactSizeIterator`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
@ -40,10 +40,14 @@ error[E0277]: the trait bound `bevy_ecs::query::Added<Foo>: ArchetypeFilter` is
|
||||||
Or<(F0, F1, F2)>
|
Or<(F0, F1, F2)>
|
||||||
Or<(F0, F1, F2, F3)>
|
Or<(F0, F1, F2, F3)>
|
||||||
Or<(F0, F1, F2, F3, F4)>
|
Or<(F0, F1, F2, F3, F4)>
|
||||||
and $N others
|
and 26 others
|
||||||
= note: required for `QueryIter<'_, '_, &Foo, bevy_ecs::query::Added<Foo>>` to implement `ExactSizeIterator`
|
= note: required for `QueryIter<'_, '_, &Foo, bevy_ecs::query::Added<Foo>>` to implement `ExactSizeIterator`
|
||||||
note: required by a bound in `is_exact_size_iterator`
|
note: required by a bound in `is_exact_size_iterator`
|
||||||
--> tests/ui/query_exact_sized_iterator_safety.rs:16:30
|
--> tests/ui/query_exact_sized_iterator_safety.rs:16:30
|
||||||
|
|
|
|
||||||
16 | fn is_exact_size_iterator<T: ExactSizeIterator>(_iter: T) {}
|
16 | fn is_exact_size_iterator<T: ExactSizeIterator>(_iter: T) {}
|
||||||
| ^^^^^^^^^^^^^^^^^ required by this bound in `is_exact_size_iterator`
|
| ^^^^^^^^^^^^^^^^^ required by this bound in `is_exact_size_iterator`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -6,10 +6,8 @@ struct A(usize);
|
||||||
fn system(mut query: Query<&mut A>) {
|
fn system(mut query: Query<&mut A>) {
|
||||||
let iter = query.iter_combinations_mut();
|
let iter = query.iter_combinations_mut();
|
||||||
|
|
||||||
// This should fail to compile.
|
|
||||||
is_iterator(iter)
|
is_iterator(iter)
|
||||||
|
//~^ E0277
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_iterator<T: Iterator>(_iter: T) {}
|
fn is_iterator<T: Iterator>(_iter: T) {}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
error[E0277]: the trait bound `&mut A: ReadOnlyQueryData` is not satisfied
|
error[E0277]: the trait bound `&mut A: ReadOnlyQueryData` is not satisfied
|
||||||
--> tests/ui/query_iter_combinations_mut_iterator_safety.rs:10:17
|
--> tests/ui/query_iter_combinations_mut_iterator_safety.rs:9:17
|
||||||
|
|
|
|
||||||
10 | is_iterator(iter)
|
9 | is_iterator(iter)
|
||||||
| ----------- ^^^^ the trait `ReadOnlyQueryData` is not implemented for `&mut A`, which is required by `QueryCombinationIter<'_, '_, &mut A, (), _>: Iterator`
|
| ----------- ^^^^ the trait `ReadOnlyQueryData` is not implemented for `&mut A`, which is required by `QueryCombinationIter<'_, '_, &mut A, (), _>: Iterator`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
@ -15,7 +15,7 @@ error[E0277]: the trait bound `&mut A: ReadOnlyQueryData` is not satisfied
|
||||||
AnyOf<(F0, F1, F2)>
|
AnyOf<(F0, F1, F2)>
|
||||||
AnyOf<(F0, F1, F2, F3)>
|
AnyOf<(F0, F1, F2, F3)>
|
||||||
AnyOf<(F0, F1, F2, F3, F4)>
|
AnyOf<(F0, F1, F2, F3, F4)>
|
||||||
and $N others
|
and 34 others
|
||||||
= note: `ReadOnlyQueryData` is implemented for `&A`, but not for `&mut A`
|
= note: `ReadOnlyQueryData` is implemented for `&A`, but not for `&mut A`
|
||||||
= note: required for `QueryCombinationIter<'_, '_, &mut A, (), _>` to implement `Iterator`
|
= note: required for `QueryCombinationIter<'_, '_, &mut A, (), _>` to implement `Iterator`
|
||||||
note: required by a bound in `is_iterator`
|
note: required by a bound in `is_iterator`
|
||||||
|
@ -23,3 +23,7 @@ note: required by a bound in `is_iterator`
|
||||||
|
|
|
|
||||||
13 | fn is_iterator<T: Iterator>(_iter: T) {}
|
13 | fn is_iterator<T: Iterator>(_iter: T) {}
|
||||||
| ^^^^^^^^ required by this bound in `is_iterator`
|
| ^^^^^^^^ required by this bound in `is_iterator`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -6,10 +6,8 @@ struct A(usize);
|
||||||
fn system(mut query: Query<&mut A>, e: Entity) {
|
fn system(mut query: Query<&mut A>, e: Entity) {
|
||||||
let iter = query.iter_many_mut([e]);
|
let iter = query.iter_many_mut([e]);
|
||||||
|
|
||||||
// This should fail to compile.
|
|
||||||
is_iterator(iter)
|
is_iterator(iter)
|
||||||
|
//~^ E0277
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_iterator<T: Iterator>(_iter: T) {}
|
fn is_iterator<T: Iterator>(_iter: T) {}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
error[E0277]: the trait bound `&mut A: ReadOnlyQueryData` is not satisfied
|
error[E0277]: the trait bound `&mut A: ReadOnlyQueryData` is not satisfied
|
||||||
--> tests/ui/query_iter_many_mut_iterator_safety.rs:10:17
|
--> tests/ui/query_iter_many_mut_iterator_safety.rs:9:17
|
||||||
|
|
|
|
||||||
10 | is_iterator(iter)
|
9 | is_iterator(iter)
|
||||||
| ----------- ^^^^ the trait `ReadOnlyQueryData` is not implemented for `&mut A`, which is required by `QueryManyIter<'_, '_, &mut A, (), std::array::IntoIter<bevy_ecs::entity::Entity, 1>>: Iterator`
|
| ----------- ^^^^ the trait `ReadOnlyQueryData` is not implemented for `&mut A`, which is required by `QueryManyIter<'_, '_, &mut A, (), std::array::IntoIter<bevy_ecs::entity::Entity, 1>>: Iterator`
|
||||||
| |
|
| |
|
||||||
| required by a bound introduced by this call
|
| required by a bound introduced by this call
|
||||||
|
@ -15,7 +15,7 @@ error[E0277]: the trait bound `&mut A: ReadOnlyQueryData` is not satisfied
|
||||||
AnyOf<(F0, F1, F2)>
|
AnyOf<(F0, F1, F2)>
|
||||||
AnyOf<(F0, F1, F2, F3)>
|
AnyOf<(F0, F1, F2, F3)>
|
||||||
AnyOf<(F0, F1, F2, F3, F4)>
|
AnyOf<(F0, F1, F2, F3, F4)>
|
||||||
and $N others
|
and 34 others
|
||||||
= note: `ReadOnlyQueryData` is implemented for `&A`, but not for `&mut A`
|
= note: `ReadOnlyQueryData` is implemented for `&A`, but not for `&mut A`
|
||||||
= note: required for `QueryManyIter<'_, '_, &mut A, (), std::array::IntoIter<bevy_ecs::entity::Entity, 1>>` to implement `Iterator`
|
= note: required for `QueryManyIter<'_, '_, &mut A, (), std::array::IntoIter<bevy_ecs::entity::Entity, 1>>` to implement `Iterator`
|
||||||
note: required by a bound in `is_iterator`
|
note: required by a bound in `is_iterator`
|
||||||
|
@ -23,3 +23,7 @@ note: required by a bound in `is_iterator`
|
||||||
|
|
|
|
||||||
13 | fn is_iterator<T: Iterator>(_iter: T) {}
|
13 | fn is_iterator<T: Iterator>(_iter: T) {}
|
||||||
| ^^^^^^^^ required by this bound in `is_iterator`
|
| ^^^^^^^^ required by this bound in `is_iterator`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -15,48 +15,56 @@ fn main() {
|
||||||
{
|
{
|
||||||
let data: &Foo = query.get(e).unwrap();
|
let data: &Foo = query.get(e).unwrap();
|
||||||
let mut data2: Mut<Foo> = query.get_mut(e).unwrap();
|
let mut data2: Mut<Foo> = query.get_mut(e).unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(data, &mut *data2); // oops UB
|
assert_eq!(data, &mut *data2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut data2: Mut<Foo> = query.get_mut(e).unwrap();
|
let mut data2: Mut<Foo> = query.get_mut(e).unwrap();
|
||||||
let data: &Foo = query.get(e).unwrap();
|
let data: &Foo = query.get(e).unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(data, &mut *data2); // oops UB
|
assert_eq!(data, &mut *data2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let data: &Foo = query.single();
|
let data: &Foo = query.single();
|
||||||
let mut data2: Mut<Foo> = query.single_mut();
|
let mut data2: Mut<Foo> = query.single_mut();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(data, &mut *data2); // oops UB
|
assert_eq!(data, &mut *data2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut data2: Mut<Foo> = query.single_mut();
|
let mut data2: Mut<Foo> = query.single_mut();
|
||||||
let data: &Foo = query.single();
|
let data: &Foo = query.single();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(data, &mut *data2); // oops UB
|
assert_eq!(data, &mut *data2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let data: &Foo = query.get_single().unwrap();
|
let data: &Foo = query.get_single().unwrap();
|
||||||
let mut data2: Mut<Foo> = query.get_single_mut().unwrap();
|
let mut data2: Mut<Foo> = query.get_single_mut().unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(data, &mut *data2); // oops UB
|
assert_eq!(data, &mut *data2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut data2: Mut<Foo> = query.get_single_mut().unwrap();
|
let mut data2: Mut<Foo> = query.get_single_mut().unwrap();
|
||||||
let data: &Foo = query.get_single().unwrap();
|
let data: &Foo = query.get_single().unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(data, &mut *data2); // oops UB
|
assert_eq!(data, &mut *data2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let data: &Foo = query.iter().next().unwrap();
|
let data: &Foo = query.iter().next().unwrap();
|
||||||
let mut data2: Mut<Foo> = query.iter_mut().next().unwrap();
|
let mut data2: Mut<Foo> = query.iter_mut().next().unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(data, &mut *data2); // oops UB
|
assert_eq!(data, &mut *data2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut data2: Mut<Foo> = query.iter_mut().next().unwrap();
|
let mut data2: Mut<Foo> = query.iter_mut().next().unwrap();
|
||||||
let data: &Foo = query.iter().next().unwrap();
|
let data: &Foo = query.iter().next().unwrap();
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(data, &mut *data2); // oops UB
|
assert_eq!(data, &mut *data2); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,6 +73,7 @@ fn main() {
|
||||||
let mut opt_data_2: Option<Mut<Foo>> = None;
|
let mut opt_data_2: Option<Mut<Foo>> = None;
|
||||||
query.iter().for_each(|data| opt_data = Some(data));
|
query.iter().for_each(|data| opt_data = Some(data));
|
||||||
query.iter_mut().for_each(|data| opt_data_2 = Some(data));
|
query.iter_mut().for_each(|data| opt_data_2 = Some(data));
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB
|
assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,6 +82,7 @@ fn main() {
|
||||||
let mut opt_data: Option<&Foo> = None;
|
let mut opt_data: Option<&Foo> = None;
|
||||||
query.iter_mut().for_each(|data| opt_data_2 = Some(data));
|
query.iter_mut().for_each(|data| opt_data_2 = Some(data));
|
||||||
query.iter().for_each(|data| opt_data = Some(data));
|
query.iter().for_each(|data| opt_data = Some(data));
|
||||||
|
//~^ E0502
|
||||||
assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB
|
assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB
|
||||||
}
|
}
|
||||||
dbg!("bye");
|
dbg!("bye");
|
||||||
|
|
|
@ -5,95 +5,109 @@ error[E0502]: cannot borrow `query` as mutable because it is also borrowed as im
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
17 | let mut data2: Mut<Foo> = query.get_mut(e).unwrap();
|
17 | let mut data2: Mut<Foo> = query.get_mut(e).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
18 | assert_eq!(data, &mut *data2); // oops UB
|
18 |
|
||||||
|
19 | assert_eq!(data, &mut *data2); // oops UB
|
||||||
| ----------------------------- immutable borrow later used here
|
| ----------------------------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
||||||
--> tests/ui/query_lifetime_safety.rs:23:30
|
--> tests/ui/query_lifetime_safety.rs:24:30
|
||||||
|
|
|
|
||||||
22 | let mut data2: Mut<Foo> = query.get_mut(e).unwrap();
|
23 | let mut data2: Mut<Foo> = query.get_mut(e).unwrap();
|
||||||
| ----- mutable borrow occurs here
|
| ----- mutable borrow occurs here
|
||||||
23 | let data: &Foo = query.get(e).unwrap();
|
24 | let data: &Foo = query.get(e).unwrap();
|
||||||
| ^^^^^ immutable borrow occurs here
|
| ^^^^^ immutable borrow occurs here
|
||||||
24 | assert_eq!(data, &mut *data2); // oops UB
|
25 |
|
||||||
|
26 | assert_eq!(data, &mut *data2); // oops UB
|
||||||
| ----- mutable borrow later used here
|
| ----- mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
||||||
--> tests/ui/query_lifetime_safety.rs:29:39
|
--> tests/ui/query_lifetime_safety.rs:31:39
|
||||||
|
|
|
|
||||||
28 | let data: &Foo = query.single();
|
30 | let data: &Foo = query.single();
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
29 | let mut data2: Mut<Foo> = query.single_mut();
|
31 | let mut data2: Mut<Foo> = query.single_mut();
|
||||||
| ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
30 | assert_eq!(data, &mut *data2); // oops UB
|
32 |
|
||||||
|
33 | assert_eq!(data, &mut *data2); // oops UB
|
||||||
| ----------------------------- immutable borrow later used here
|
| ----------------------------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
||||||
--> tests/ui/query_lifetime_safety.rs:35:30
|
--> tests/ui/query_lifetime_safety.rs:38:30
|
||||||
|
|
|
|
||||||
34 | let mut data2: Mut<Foo> = query.single_mut();
|
37 | let mut data2: Mut<Foo> = query.single_mut();
|
||||||
| ----- mutable borrow occurs here
|
| ----- mutable borrow occurs here
|
||||||
35 | let data: &Foo = query.single();
|
38 | let data: &Foo = query.single();
|
||||||
| ^^^^^ immutable borrow occurs here
|
| ^^^^^ immutable borrow occurs here
|
||||||
36 | assert_eq!(data, &mut *data2); // oops UB
|
39 |
|
||||||
|
40 | assert_eq!(data, &mut *data2); // oops UB
|
||||||
| ----- mutable borrow later used here
|
| ----- mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
||||||
--> tests/ui/query_lifetime_safety.rs:41:39
|
--> tests/ui/query_lifetime_safety.rs:45:39
|
||||||
|
|
|
|
||||||
40 | let data: &Foo = query.get_single().unwrap();
|
44 | let data: &Foo = query.get_single().unwrap();
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
41 | let mut data2: Mut<Foo> = query.get_single_mut().unwrap();
|
45 | let mut data2: Mut<Foo> = query.get_single_mut().unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
42 | assert_eq!(data, &mut *data2); // oops UB
|
46 |
|
||||||
|
47 | assert_eq!(data, &mut *data2); // oops UB
|
||||||
| ----------------------------- immutable borrow later used here
|
| ----------------------------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
||||||
--> tests/ui/query_lifetime_safety.rs:47:30
|
--> tests/ui/query_lifetime_safety.rs:52:30
|
||||||
|
|
|
|
||||||
46 | let mut data2: Mut<Foo> = query.get_single_mut().unwrap();
|
51 | let mut data2: Mut<Foo> = query.get_single_mut().unwrap();
|
||||||
| ----- mutable borrow occurs here
|
| ----- mutable borrow occurs here
|
||||||
47 | let data: &Foo = query.get_single().unwrap();
|
52 | let data: &Foo = query.get_single().unwrap();
|
||||||
| ^^^^^ immutable borrow occurs here
|
| ^^^^^ immutable borrow occurs here
|
||||||
48 | assert_eq!(data, &mut *data2); // oops UB
|
53 |
|
||||||
| ----- mutable borrow later used here
|
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
|
||||||
--> tests/ui/query_lifetime_safety.rs:53:39
|
|
||||||
|
|
|
||||||
52 | let data: &Foo = query.iter().next().unwrap();
|
|
||||||
| ----- immutable borrow occurs here
|
|
||||||
53 | let mut data2: Mut<Foo> = query.iter_mut().next().unwrap();
|
|
||||||
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
|
||||||
54 | assert_eq!(data, &mut *data2); // oops UB
|
54 | assert_eq!(data, &mut *data2); // oops UB
|
||||||
| ----------------------------- immutable borrow later used here
|
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
|
||||||
--> tests/ui/query_lifetime_safety.rs:59:30
|
|
||||||
|
|
|
||||||
58 | let mut data2: Mut<Foo> = query.iter_mut().next().unwrap();
|
|
||||||
| ----- mutable borrow occurs here
|
|
||||||
59 | let data: &Foo = query.iter().next().unwrap();
|
|
||||||
| ^^^^^ immutable borrow occurs here
|
|
||||||
60 | assert_eq!(data, &mut *data2); // oops UB
|
|
||||||
| ----- mutable borrow later used here
|
| ----- mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
||||||
--> tests/ui/query_lifetime_safety.rs:67:13
|
--> tests/ui/query_lifetime_safety.rs:59:39
|
||||||
|
|
|
|
||||||
66 | query.iter().for_each(|data| opt_data = Some(data));
|
58 | let data: &Foo = query.iter().next().unwrap();
|
||||||
|
| ----- immutable borrow occurs here
|
||||||
|
59 | let mut data2: Mut<Foo> = query.iter_mut().next().unwrap();
|
||||||
|
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
|
60 |
|
||||||
|
61 | assert_eq!(data, &mut *data2); // oops UB
|
||||||
|
| ----------------------------- immutable borrow later used here
|
||||||
|
|
||||||
|
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
||||||
|
--> tests/ui/query_lifetime_safety.rs:66:30
|
||||||
|
|
|
||||||
|
65 | let mut data2: Mut<Foo> = query.iter_mut().next().unwrap();
|
||||||
|
| ----- mutable borrow occurs here
|
||||||
|
66 | let data: &Foo = query.iter().next().unwrap();
|
||||||
|
| ^^^^^ immutable borrow occurs here
|
||||||
|
67 |
|
||||||
|
68 | assert_eq!(data, &mut *data2); // oops UB
|
||||||
|
| ----- mutable borrow later used here
|
||||||
|
|
||||||
|
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
||||||
|
--> tests/ui/query_lifetime_safety.rs:75:13
|
||||||
|
|
|
||||||
|
74 | query.iter().for_each(|data| opt_data = Some(data));
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
67 | query.iter_mut().for_each(|data| opt_data_2 = Some(data));
|
75 | query.iter_mut().for_each(|data| opt_data_2 = Some(data));
|
||||||
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
68 | assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB
|
76 |
|
||||||
|
77 | assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB
|
||||||
| -------- immutable borrow later used here
|
| -------- immutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
||||||
--> tests/ui/query_lifetime_safety.rs:75:13
|
--> tests/ui/query_lifetime_safety.rs:84:13
|
||||||
|
|
|
|
||||||
74 | query.iter_mut().for_each(|data| opt_data_2 = Some(data));
|
83 | query.iter_mut().for_each(|data| opt_data_2 = Some(data));
|
||||||
| ----- mutable borrow occurs here
|
| ----- mutable borrow occurs here
|
||||||
75 | query.iter().for_each(|data| opt_data = Some(data));
|
84 | query.iter().for_each(|data| opt_data = Some(data));
|
||||||
| ^^^^^ immutable borrow occurs here
|
| ^^^^^ immutable borrow occurs here
|
||||||
76 | assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB
|
85 |
|
||||||
|
86 | assert_eq!(opt_data.unwrap(), &mut *opt_data_2.unwrap()); // oops UB
|
||||||
| ---------- mutable borrow later used here
|
| ---------- mutable borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 10 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0502`.
|
||||||
|
|
|
@ -7,11 +7,13 @@ fn for_loops(mut query: Query<&mut Foo>) {
|
||||||
// this should fail to compile
|
// this should fail to compile
|
||||||
for _ in query.iter_mut() {
|
for _ in query.iter_mut() {
|
||||||
for _ in query.to_readonly().iter() {}
|
for _ in query.to_readonly().iter() {}
|
||||||
|
//~^ E0502
|
||||||
}
|
}
|
||||||
|
|
||||||
// this should fail to compile
|
// this should fail to compile
|
||||||
for _ in query.to_readonly().iter() {
|
for _ in query.to_readonly().iter() {
|
||||||
for _ in query.iter_mut() {}
|
for _ in query.iter_mut() {}
|
||||||
|
//~^ E0502
|
||||||
}
|
}
|
||||||
|
|
||||||
// this should *not* fail to compile
|
// this should *not* fail to compile
|
||||||
|
@ -37,6 +39,7 @@ fn single_mut_query(mut query: Query<&mut Foo>) {
|
||||||
|
|
||||||
// This solves "temporary value dropped while borrowed"
|
// This solves "temporary value dropped while borrowed"
|
||||||
let readonly_query = query.to_readonly();
|
let readonly_query = query.to_readonly();
|
||||||
|
//~^ E0502
|
||||||
|
|
||||||
let ref_foo = readonly_query.single();
|
let ref_foo = readonly_query.single();
|
||||||
|
|
||||||
|
@ -53,6 +56,7 @@ fn single_mut_query(mut query: Query<&mut Foo>) {
|
||||||
let ref_foo = readonly_query.single();
|
let ref_foo = readonly_query.single();
|
||||||
|
|
||||||
let mut mut_foo = query.single_mut();
|
let mut mut_foo = query.single_mut();
|
||||||
|
//~^ E0502
|
||||||
|
|
||||||
println!("{ref_foo:?}");
|
println!("{ref_foo:?}");
|
||||||
|
|
||||||
|
@ -71,5 +75,3 @@ fn single_mut_query(mut query: Query<&mut Foo>) {
|
||||||
println!("{readonly_foo:?}, {query_foo:?}");
|
println!("{readonly_foo:?}, {query_foo:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -10,36 +10,40 @@ error[E0502]: cannot borrow `query` as immutable because it is also borrowed as
|
||||||
| ^^^^^ immutable borrow occurs here
|
| ^^^^^ immutable borrow occurs here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
||||||
--> tests/ui/query_to_readonly.rs:14:18
|
--> tests/ui/query_to_readonly.rs:15:18
|
||||||
|
|
|
|
||||||
13 | for _ in query.to_readonly().iter() {
|
14 | for _ in query.to_readonly().iter() {
|
||||||
| --------------------------
|
| --------------------------
|
||||||
| |
|
| |
|
||||||
| immutable borrow occurs here
|
| immutable borrow occurs here
|
||||||
| immutable borrow later used here
|
| immutable borrow later used here
|
||||||
14 | for _ in query.iter_mut() {}
|
15 | for _ in query.iter_mut() {}
|
||||||
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
error[E0502]: cannot borrow `query` as immutable because it is also borrowed as mutable
|
||||||
--> tests/ui/query_to_readonly.rs:39:30
|
--> tests/ui/query_to_readonly.rs:41:30
|
||||||
|
|
|
|
||||||
36 | let mut mut_foo = query.single_mut();
|
38 | let mut mut_foo = query.single_mut();
|
||||||
| ----- mutable borrow occurs here
|
| ----- mutable borrow occurs here
|
||||||
...
|
...
|
||||||
39 | let readonly_query = query.to_readonly();
|
41 | let readonly_query = query.to_readonly();
|
||||||
| ^^^^^ immutable borrow occurs here
|
| ^^^^^ immutable borrow occurs here
|
||||||
...
|
...
|
||||||
43 | *mut_foo = Foo;
|
46 | *mut_foo = Foo;
|
||||||
| ------- mutable borrow later used here
|
| ------- mutable borrow later used here
|
||||||
|
|
||||||
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
error[E0502]: cannot borrow `query` as mutable because it is also borrowed as immutable
|
||||||
--> tests/ui/query_to_readonly.rs:55:27
|
--> tests/ui/query_to_readonly.rs:58:27
|
||||||
|
|
|
|
||||||
51 | let readonly_query = query.to_readonly();
|
54 | let readonly_query = query.to_readonly();
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
...
|
...
|
||||||
55 | let mut mut_foo = query.single_mut();
|
58 | let mut mut_foo = query.single_mut();
|
||||||
| ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
56 |
|
...
|
||||||
57 | println!("{ref_foo:?}");
|
61 | println!("{ref_foo:?}");
|
||||||
| ----------- immutable borrow later used here
|
| ----------- immutable borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0502`.
|
||||||
|
|
|
@ -17,6 +17,7 @@ fn main() {
|
||||||
{
|
{
|
||||||
let mut lens_a = query.transmute_lens::<&mut Foo>();
|
let mut lens_a = query.transmute_lens::<&mut Foo>();
|
||||||
let mut lens_b = query.transmute_lens::<&mut Foo>();
|
let mut lens_b = query.transmute_lens::<&mut Foo>();
|
||||||
|
//~^ E0499
|
||||||
|
|
||||||
let mut query_a = lens_a.query();
|
let mut query_a = lens_a.query();
|
||||||
let mut query_b = lens_b.query();
|
let mut query_b = lens_b.query();
|
||||||
|
@ -31,6 +32,7 @@ fn main() {
|
||||||
|
|
||||||
let mut query_a = lens.query();
|
let mut query_a = lens.query();
|
||||||
let mut query_b = lens.query();
|
let mut query_b = lens.query();
|
||||||
|
//~^ E0499
|
||||||
|
|
||||||
let a = query_a.single_mut();
|
let a = query_a.single_mut();
|
||||||
let b = query_b.single_mut(); // oops 2 mutable references to same Foo
|
let b = query_b.single_mut(); // oops 2 mutable references to same Foo
|
||||||
|
|
|
@ -5,17 +5,21 @@ error[E0499]: cannot borrow `query` as mutable more than once at a time
|
||||||
| ----- first mutable borrow occurs here
|
| ----- first mutable borrow occurs here
|
||||||
19 | let mut lens_b = query.transmute_lens::<&mut Foo>();
|
19 | let mut lens_b = query.transmute_lens::<&mut Foo>();
|
||||||
| ^^^^^ second mutable borrow occurs here
|
| ^^^^^ second mutable borrow occurs here
|
||||||
20 |
|
...
|
||||||
21 | let mut query_a = lens_a.query();
|
22 | let mut query_a = lens_a.query();
|
||||||
| ------ first borrow later used here
|
| ------ first borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow `lens` as mutable more than once at a time
|
error[E0499]: cannot borrow `lens` as mutable more than once at a time
|
||||||
--> tests/ui/query_transmute_safety.rs:33:27
|
--> tests/ui/query_transmute_safety.rs:34:27
|
||||||
|
|
|
|
||||||
32 | let mut query_a = lens.query();
|
33 | let mut query_a = lens.query();
|
||||||
| ---- first mutable borrow occurs here
|
| ---- first mutable borrow occurs here
|
||||||
33 | let mut query_b = lens.query();
|
34 | let mut query_b = lens.query();
|
||||||
| ^^^^ second mutable borrow occurs here
|
| ^^^^ second mutable borrow occurs here
|
||||||
34 |
|
...
|
||||||
35 | let a = query_a.single_mut();
|
37 | let a = query_a.single_mut();
|
||||||
| ------- first borrow later used here
|
| ------- first borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0499`.
|
||||||
|
|
|
@ -10,12 +10,11 @@ struct Mutable<'w, 's> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
// Ideally we'd use:
|
|
||||||
// let mut world = World::default();
|
let mut world = World::default();
|
||||||
// let state = SystemState::<Mutable>::new(&mut world);
|
let state = SystemState::<Mutable>::new(&mut world);
|
||||||
// state.get(&world);
|
state.get(&world);
|
||||||
// But that makes the test show absolute paths
|
//~^ E0277
|
||||||
assert_readonly::<Mutable>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_readonly<P>()
|
fn assert_readonly<P>()
|
||||||
|
|
|
@ -1,36 +1,32 @@
|
||||||
warning: unused import: `SystemState`
|
|
||||||
--> tests/ui/system_param_derive_readonly.rs:2:58
|
|
||||||
|
|
|
||||||
2 | use bevy_ecs::system::{ReadOnlySystemParam, SystemParam, SystemState};
|
|
||||||
| ^^^^^^^^^^^
|
|
||||||
|
|
|
||||||
= note: `#[warn(unused_imports)]` on by default
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `&'static mut Foo: ReadOnlyQueryData` is not satisfied
|
error[E0277]: the trait bound `&'static mut Foo: ReadOnlyQueryData` is not satisfied
|
||||||
--> tests/ui/system_param_derive_readonly.rs:18:23
|
--> tests/ui/system_param_derive_readonly.rs:16:11
|
||||||
|
|
|
|
||||||
18 | assert_readonly::<Mutable>();
|
16 | state.get(&world);
|
||||||
| ^^^^^^^ the trait `ReadOnlyQueryData` is not implemented for `&'static mut Foo`, which is required by `Mutable<'_, '_>: ReadOnlySystemParam`
|
| ^^^ the trait `ReadOnlyQueryData` is not implemented for `&'static mut Foo`, which is required by `Mutable<'_, '_>: ReadOnlySystemParam`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `ReadOnlyQueryData`:
|
= help: the following other types implement trait `ReadOnlyQueryData`:
|
||||||
bevy_ecs::change_detection::Ref<'__w, T>
|
bevy_ecs::change_detection::Ref<'__w, T>
|
||||||
Has<T>
|
Has<T>
|
||||||
AnyOf<()>
|
AnyOf<()>
|
||||||
AnyOf<(F0,)>
|
AnyOf<(F0,)>
|
||||||
AnyOf<(F0, F1)>
|
AnyOf<(F0, F1)>
|
||||||
AnyOf<(F0, F1, F2)>
|
AnyOf<(F0, F1, F2)>
|
||||||
AnyOf<(F0, F1, F2, F3)>
|
AnyOf<(F0, F1, F2, F3)>
|
||||||
AnyOf<(F0, F1, F2, F3, F4)>
|
AnyOf<(F0, F1, F2, F3, F4)>
|
||||||
and $N others
|
and 34 others
|
||||||
= note: `ReadOnlyQueryData` is implemented for `&'static Foo`, but not for `&'static mut Foo`
|
= note: `ReadOnlyQueryData` is implemented for `&'static Foo`, but not for `&'static mut Foo`
|
||||||
= note: required for `bevy_ecs::system::Query<'_, '_, &'static mut Foo>` to implement `ReadOnlySystemParam`
|
= note: required for `bevy_ecs::system::Query<'_, '_, &'static mut Foo>` to implement `ReadOnlySystemParam`
|
||||||
= note: 1 redundant requirement hidden
|
= note: 1 redundant requirement hidden
|
||||||
= note: required for `Mutable<'_, '_>` to implement `ReadOnlySystemParam`
|
= note: required for `Mutable<'_, '_>` to implement `ReadOnlySystemParam`
|
||||||
note: required by a bound in `assert_readonly`
|
note: required by a bound in `SystemState::<Param>::get`
|
||||||
--> tests/ui/system_param_derive_readonly.rs:23:8
|
--> $BEVY_ROOT/crates/bevy_ecs/src/system/function_system.rs:215:16
|
||||||
|
|
|
|
||||||
21 | fn assert_readonly<P>()
|
213 | pub fn get<'w, 's>(&'s mut self, world: &'w World) -> SystemParamItem<'w, 's, Param>
|
||||||
| --------------- required by a bound in this function
|
| --- required by a bound in this associated function
|
||||||
22 | where
|
214 | where
|
||||||
23 | P: ReadOnlySystemParam,
|
215 | Param: ReadOnlySystemParam,
|
||||||
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_readonly`
|
| ^^^^^^^^^^^^^^^^^^^ required by this bound in `SystemState::<Param>::get`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -6,8 +6,6 @@ struct A(usize);
|
||||||
fn system(mut query: Query<&mut A>, e: Entity) {
|
fn system(mut query: Query<&mut A>, e: Entity) {
|
||||||
let a1 = query.get_mut(e).unwrap();
|
let a1 = query.get_mut(e).unwrap();
|
||||||
let a2 = query.get_mut(e).unwrap();
|
let a2 = query.get_mut(e).unwrap();
|
||||||
// this should fail to compile
|
//~^ E0499
|
||||||
println!("{} {}", a1.0, a2.0);
|
println!("{} {}", a1.0, a2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -5,6 +5,10 @@ error[E0499]: cannot borrow `query` as mutable more than once at a time
|
||||||
| ----- first mutable borrow occurs here
|
| ----- first mutable borrow occurs here
|
||||||
8 | let a2 = query.get_mut(e).unwrap();
|
8 | let a2 = query.get_mut(e).unwrap();
|
||||||
| ^^^^^ second mutable borrow occurs here
|
| ^^^^^ second mutable borrow occurs here
|
||||||
9 | // this should fail to compile
|
9 |
|
||||||
10 | println!("{} {}", a1.0, a2.0);
|
10 | println!("{} {}", a1.0, a2.0);
|
||||||
| -- first borrow later used here
|
| -- first borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0499`.
|
||||||
|
|
|
@ -6,8 +6,6 @@ struct A(usize);
|
||||||
fn system(mut query: Query<&mut A>, e: Entity) {
|
fn system(mut query: Query<&mut A>, e: Entity) {
|
||||||
let a1 = query.get_many([e, e]).unwrap();
|
let a1 = query.get_many([e, e]).unwrap();
|
||||||
let a2 = query.get_mut(e).unwrap();
|
let a2 = query.get_mut(e).unwrap();
|
||||||
// this should fail to compile
|
//~^ E0502
|
||||||
println!("{} {}", a1[0].0, a2.0);
|
println!("{} {}", a1[0].0, a2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -5,6 +5,10 @@ error[E0502]: cannot borrow `query` as mutable because it is also borrowed as im
|
||||||
| ----- immutable borrow occurs here
|
| ----- immutable borrow occurs here
|
||||||
8 | let a2 = query.get_mut(e).unwrap();
|
8 | let a2 = query.get_mut(e).unwrap();
|
||||||
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
| ^^^^^^^^^^^^^^^^ mutable borrow occurs here
|
||||||
9 | // this should fail to compile
|
9 |
|
||||||
10 | println!("{} {}", a1[0].0, a2.0);
|
10 | println!("{} {}", a1[0].0, a2.0);
|
||||||
| ----- immutable borrow later used here
|
| ----- immutable borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0502`.
|
||||||
|
|
|
@ -6,8 +6,6 @@ struct A(usize);
|
||||||
fn system(mut query: Query<&mut A>, e: Entity) {
|
fn system(mut query: Query<&mut A>, e: Entity) {
|
||||||
let a1 = query.get_many_mut([e, e]).unwrap();
|
let a1 = query.get_many_mut([e, e]).unwrap();
|
||||||
let a2 = query.get_mut(e).unwrap();
|
let a2 = query.get_mut(e).unwrap();
|
||||||
// this should fail to compile
|
//~^ E0499
|
||||||
println!("{} {}", a1[0].0, a2.0);
|
println!("{} {}", a1[0].0, a2.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -5,6 +5,10 @@ error[E0499]: cannot borrow `query` as mutable more than once at a time
|
||||||
| ----- first mutable borrow occurs here
|
| ----- first mutable borrow occurs here
|
||||||
8 | let a2 = query.get_mut(e).unwrap();
|
8 | let a2 = query.get_mut(e).unwrap();
|
||||||
| ^^^^^ second mutable borrow occurs here
|
| ^^^^^ second mutable borrow occurs here
|
||||||
9 | // this should fail to compile
|
9 |
|
||||||
10 | println!("{} {}", a1[0].0, a2.0);
|
10 | println!("{} {}", a1[0].0, a2.0);
|
||||||
| ----- first borrow later used here
|
| ----- first borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0499`.
|
||||||
|
|
|
@ -8,10 +8,8 @@ fn system(mut query: Query<&mut A>) {
|
||||||
let a = &mut *iter.next().unwrap();
|
let a = &mut *iter.next().unwrap();
|
||||||
|
|
||||||
let mut iter2 = query.iter_mut();
|
let mut iter2 = query.iter_mut();
|
||||||
|
//~^ E0499
|
||||||
let _ = &mut *iter2.next().unwrap();
|
let _ = &mut *iter2.next().unwrap();
|
||||||
|
|
||||||
// this should fail to compile
|
|
||||||
println!("{}", a.0);
|
println!("{}", a.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -9,3 +9,7 @@ error[E0499]: cannot borrow `query` as mutable more than once at a time
|
||||||
...
|
...
|
||||||
14 | println!("{}", a.0);
|
14 | println!("{}", a.0);
|
||||||
| --- first borrow later used here
|
| --- first borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0499`.
|
||||||
|
|
|
@ -6,10 +6,8 @@ struct A(usize);
|
||||||
fn system(mut query: Query<&mut A>, e: Entity) {
|
fn system(mut query: Query<&mut A>, e: Entity) {
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
let mut iter = query.iter_many_mut([e, e]);
|
let mut iter = query.iter_many_mut([e, e]);
|
||||||
|
//~v E0499
|
||||||
while let Some(a) = iter.fetch_next() {
|
while let Some(a) = iter.fetch_next() {
|
||||||
// this should fail to compile
|
|
||||||
results.push(a);
|
results.push(a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
error[E0499]: cannot borrow `iter` as mutable more than once at a time
|
error[E0499]: cannot borrow `iter` as mutable more than once at a time
|
||||||
--> tests/ui/system_query_iter_many_mut_lifetime_safety.rs:9:25
|
--> tests/ui/system_query_iter_many_mut_lifetime_safety.rs:10:25
|
||||||
|
|
|
|
||||||
9 | while let Some(a) = iter.fetch_next() {
|
10 | while let Some(a) = iter.fetch_next() {
|
||||||
| ^^^^ `iter` was mutably borrowed here in the previous iteration of the loop
|
| ^^^^ `iter` was mutably borrowed here in the previous iteration of the loop
|
||||||
10 | // this should fail to compile
|
|
||||||
11 | results.push(a);
|
11 | results.push(a);
|
||||||
| ------- first borrow used here, in later iteration of loop
|
| ------- first borrow used here, in later iteration of loop
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0499`.
|
||||||
|
|
|
@ -8,6 +8,7 @@ fn query_set(mut queries: ParamSet<(Query<&mut A>, Query<&A>)>, e: Entity) {
|
||||||
let mut b = q2.get_mut(e).unwrap();
|
let mut b = q2.get_mut(e).unwrap();
|
||||||
|
|
||||||
let q1 = queries.p1();
|
let q1 = queries.p1();
|
||||||
|
//~^ E0499
|
||||||
let a = q1.get(e).unwrap();
|
let a = q1.get(e).unwrap();
|
||||||
|
|
||||||
// this should fail to compile
|
// this should fail to compile
|
||||||
|
@ -19,10 +20,9 @@ fn query_set_flip(mut queries: ParamSet<(Query<&mut A>, Query<&A>)>, e: Entity)
|
||||||
let a = q1.get(e).unwrap();
|
let a = q1.get(e).unwrap();
|
||||||
|
|
||||||
let mut q2 = queries.p0();
|
let mut q2 = queries.p0();
|
||||||
|
//~^ E0499
|
||||||
let mut b = q2.get_mut(e).unwrap();
|
let mut b = q2.get_mut(e).unwrap();
|
||||||
|
|
||||||
// this should fail to compile
|
// this should fail to compile
|
||||||
b.0 = a.0
|
b.0 = a.0
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -7,17 +7,21 @@ error[E0499]: cannot borrow `queries` as mutable more than once at a time
|
||||||
10 | let q1 = queries.p1();
|
10 | let q1 = queries.p1();
|
||||||
| ^^^^^^^ second mutable borrow occurs here
|
| ^^^^^^^ second mutable borrow occurs here
|
||||||
...
|
...
|
||||||
14 | b.0 = a.0
|
15 | b.0 = a.0
|
||||||
| - first borrow later used here
|
| - first borrow later used here
|
||||||
|
|
||||||
error[E0499]: cannot borrow `queries` as mutable more than once at a time
|
error[E0499]: cannot borrow `queries` as mutable more than once at a time
|
||||||
--> tests/ui/system_query_set_get_lifetime_safety.rs:21:18
|
--> tests/ui/system_query_set_get_lifetime_safety.rs:22:18
|
||||||
|
|
|
|
||||||
18 | let q1 = queries.p1();
|
19 | let q1 = queries.p1();
|
||||||
| ------- first mutable borrow occurs here
|
| ------- first mutable borrow occurs here
|
||||||
...
|
...
|
||||||
21 | let mut q2 = queries.p0();
|
22 | let mut q2 = queries.p0();
|
||||||
| ^^^^^^^ second mutable borrow occurs here
|
| ^^^^^^^ second mutable borrow occurs here
|
||||||
...
|
...
|
||||||
25 | b.0 = a.0
|
27 | b.0 = a.0
|
||||||
| --- first borrow later used here
|
| --- first borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0499`.
|
||||||
|
|
|
@ -9,10 +9,10 @@ fn query_set(mut queries: ParamSet<(Query<&mut A>, Query<&A>)>) {
|
||||||
let mut b = iter2.next().unwrap();
|
let mut b = iter2.next().unwrap();
|
||||||
|
|
||||||
let q1 = queries.p1();
|
let q1 = queries.p1();
|
||||||
|
//~^ E0499
|
||||||
let mut iter = q1.iter();
|
let mut iter = q1.iter();
|
||||||
let a = &*iter.next().unwrap();
|
let a = &*iter.next().unwrap();
|
||||||
|
|
||||||
// this should fail to compile
|
|
||||||
b.0 = a.0
|
b.0 = a.0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +22,9 @@ fn query_set_flip(mut queries: ParamSet<(Query<&mut A>, Query<&A>)>) {
|
||||||
let a = &*iter.next().unwrap();
|
let a = &*iter.next().unwrap();
|
||||||
|
|
||||||
let mut q2 = queries.p0();
|
let mut q2 = queries.p0();
|
||||||
|
//~^ E0499
|
||||||
let mut iter2 = q2.iter_mut();
|
let mut iter2 = q2.iter_mut();
|
||||||
let mut b = iter2.next().unwrap();
|
let mut b = iter2.next().unwrap();
|
||||||
|
|
||||||
// this should fail to compile
|
|
||||||
b.0 = a.0;
|
b.0 = a.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -21,3 +21,7 @@ error[E0499]: cannot borrow `queries` as mutable more than once at a time
|
||||||
...
|
...
|
||||||
29 | b.0 = a.0;
|
29 | b.0 = a.0;
|
||||||
| --- first borrow later used here
|
| --- first borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0499`.
|
||||||
|
|
|
@ -18,11 +18,9 @@ impl State {
|
||||||
let a1 = q1.get(entity).unwrap();
|
let a1 = q1.get(entity).unwrap();
|
||||||
|
|
||||||
let mut q2 = self.state_w.get_mut(world);
|
let mut q2 = self.state_w.get_mut(world);
|
||||||
|
//~^ E0502
|
||||||
let _ = q2.get_mut(entity).unwrap();
|
let _ = q2.get_mut(entity).unwrap();
|
||||||
|
|
||||||
// this should fail to compile
|
|
||||||
println!("{}", a1.0);
|
println!("{}", a1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -9,3 +9,7 @@ error[E0502]: cannot borrow `*world` as mutable because it is also borrowed as i
|
||||||
...
|
...
|
||||||
24 | println!("{}", a1.0);
|
24 | println!("{}", a1.0);
|
||||||
| ---- immutable borrow later used here
|
| ---- immutable borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0502`.
|
||||||
|
|
|
@ -18,11 +18,9 @@ impl State {
|
||||||
let a1 = q1.iter().next().unwrap();
|
let a1 = q1.iter().next().unwrap();
|
||||||
|
|
||||||
let mut q2 = self.state_w.get_mut(world);
|
let mut q2 = self.state_w.get_mut(world);
|
||||||
|
//~^ E0502
|
||||||
let _ = q2.iter_mut().next().unwrap();
|
let _ = q2.iter_mut().next().unwrap();
|
||||||
|
|
||||||
// this should fail to compile
|
|
||||||
println!("{}", a1.0);
|
println!("{}", a1.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -9,3 +9,7 @@ error[E0502]: cannot borrow `*world` as mutable because it is also borrowed as i
|
||||||
...
|
...
|
||||||
24 | println!("{}", a1.0);
|
24 | println!("{}", a1.0);
|
||||||
| ---- immutable borrow later used here
|
| ---- immutable borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0502`.
|
||||||
|
|
|
@ -16,6 +16,7 @@ fn main() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
// this should fail to compile due to the later use of mut_vec
|
// this should fail to compile due to the later use of mut_vec
|
||||||
query.iter().collect::<Vec<&A>>(),
|
query.iter().collect::<Vec<&A>>(),
|
||||||
|
//~^ E0502
|
||||||
vec![&A(1), &A(2)],
|
vec![&A(1), &A(2)],
|
||||||
"both components returned by iter of &mut"
|
"both components returned by iter of &mut"
|
||||||
);
|
);
|
||||||
|
|
|
@ -7,5 +7,9 @@ error[E0502]: cannot borrow `query` as immutable because it is also borrowed as
|
||||||
18 | query.iter().collect::<Vec<&A>>(),
|
18 | query.iter().collect::<Vec<&A>>(),
|
||||||
| ^^^^^ immutable borrow occurs here
|
| ^^^^^ immutable borrow occurs here
|
||||||
...
|
...
|
||||||
23 | mut_vec.iter().map(|m| **m).collect::<Vec<A>>(),
|
24 | mut_vec.iter().map(|m| **m).collect::<Vec<A>>(),
|
||||||
| ------- mutable borrow later used here
|
| ------- mutable borrow later used here
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0502`.
|
||||||
|
|
|
@ -6,6 +6,7 @@ struct Foo;
|
||||||
|
|
||||||
#[derive(QueryData)]
|
#[derive(QueryData)]
|
||||||
struct MutableUnmarked {
|
struct MutableUnmarked {
|
||||||
|
//~v E0277
|
||||||
a: &'static mut Foo,
|
a: &'static mut Foo,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,7 +18,6 @@ struct MutableMarked {
|
||||||
|
|
||||||
#[derive(QueryData)]
|
#[derive(QueryData)]
|
||||||
struct NestedMutableUnmarked {
|
struct NestedMutableUnmarked {
|
||||||
|
//~v E0277
|
||||||
a: MutableMarked,
|
a: MutableMarked,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
error[E0277]: the trait bound `&'static mut Foo: ReadOnlyQueryData` is not satisfied
|
error[E0277]: the trait bound `&'static mut Foo: ReadOnlyQueryData` is not satisfied
|
||||||
--> tests/ui/world_query_derive.rs:9:8
|
--> tests/ui/world_query_derive.rs:10:8
|
||||||
|
|
|
|
||||||
9 | a: &'static mut Foo,
|
10 | a: &'static mut Foo,
|
||||||
| ^^^^^^^^^^^^^^^^ the trait `ReadOnlyQueryData` is not implemented for `&'static mut Foo`
|
| ^^^^^^^^^^^^^^^^ the trait `ReadOnlyQueryData` is not implemented for `&'static mut Foo`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `ReadOnlyQueryData`:
|
= help: the following other types implement trait `ReadOnlyQueryData`:
|
||||||
MutableUnmarked
|
MutableUnmarked
|
||||||
MutableMarkedReadOnly
|
MutableMarkedReadOnly
|
||||||
NestedMutableUnmarked
|
NestedMutableUnmarked
|
||||||
bevy_ecs::change_detection::Ref<'__w, T>
|
bevy_ecs::change_detection::Ref<'__w, T>
|
||||||
Has<T>
|
Has<T>
|
||||||
AnyOf<()>
|
AnyOf<()>
|
||||||
AnyOf<(F0,)>
|
AnyOf<(F0,)>
|
||||||
AnyOf<(F0, F1)>
|
AnyOf<(F0, F1)>
|
||||||
and $N others
|
and 37 others
|
||||||
note: required by a bound in `_::assert_readonly`
|
note: required by a bound in `_::assert_readonly`
|
||||||
--> tests/ui/world_query_derive.rs:7:10
|
--> tests/ui/world_query_derive.rs:7:10
|
||||||
|
|
|
|
||||||
7 | #[derive(QueryData)]
|
7 | #[derive(QueryData)]
|
||||||
| ^^^^^^^^^ required by this bound in `assert_readonly`
|
| ^^^^^^^^^ required by this bound in `assert_readonly`
|
||||||
= note: this error originates in the derive macro `QueryData` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `QueryData` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0277]: the trait bound `MutableMarked: ReadOnlyQueryData` is not satisfied
|
error[E0277]: the trait bound `MutableMarked: ReadOnlyQueryData` is not satisfied
|
||||||
--> tests/ui/world_query_derive.rs:20:8
|
--> tests/ui/world_query_derive.rs:22:8
|
||||||
|
|
|
|
||||||
20 | a: MutableMarked,
|
22 | a: MutableMarked,
|
||||||
| ^^^^^^^^^^^^^ the trait `ReadOnlyQueryData` is not implemented for `MutableMarked`
|
| ^^^^^^^^^^^^^ the trait `ReadOnlyQueryData` is not implemented for `MutableMarked`
|
||||||
|
|
|
|
||||||
= help: the following other types implement trait `ReadOnlyQueryData`:
|
= help: the following other types implement trait `ReadOnlyQueryData`:
|
||||||
|
@ -36,10 +36,14 @@ error[E0277]: the trait bound `MutableMarked: ReadOnlyQueryData` is not satisfie
|
||||||
AnyOf<()>
|
AnyOf<()>
|
||||||
AnyOf<(F0,)>
|
AnyOf<(F0,)>
|
||||||
AnyOf<(F0, F1)>
|
AnyOf<(F0, F1)>
|
||||||
and $N others
|
and 37 others
|
||||||
note: required by a bound in `_::assert_readonly`
|
note: required by a bound in `_::assert_readonly`
|
||||||
--> tests/ui/world_query_derive.rs:18:10
|
--> tests/ui/world_query_derive.rs:19:10
|
||||||
|
|
|
|
||||||
18 | #[derive(QueryData)]
|
19 | #[derive(QueryData)]
|
||||||
| ^^^^^^^^^ required by this bound in `assert_readonly`
|
| ^^^^^^^^^ required by this bound in `assert_readonly`
|
||||||
= note: this error originates in the derive macro `QueryData` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `QueryData` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
||||||
|
|
|
@ -8,5 +8,12 @@ license = "MIT OR Apache-2.0"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bevy_derive = { path = "../bevy_derive" }
|
# ui_test dies if we don't specify the version. See oli-obk/ui_test#211
|
||||||
trybuild = "1.0.71"
|
bevy_derive = { path = "../bevy_derive", version = "0.14.0-dev" }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
bevy_compile_test_utils = { path = "../bevy_compile_test_utils" }
|
||||||
|
|
||||||
|
[[test]]
|
||||||
|
name = "derive"
|
||||||
|
harness = false
|
||||||
|
|
|
@ -4,3 +4,5 @@ This crate is not part of the Bevy workspace in order to not fail `crater` tests
|
||||||
The tests assert on the exact compiler errors and can easily fail for new Rust versions due to updated compiler errors (e.g. changes in spans).
|
The tests assert on the exact compiler errors and can easily fail for new Rust versions due to updated compiler errors (e.g. changes in spans).
|
||||||
|
|
||||||
The `CI` workflow executes these tests on the stable rust toolchain (see [tools/ci](../../tools/ci/src/main.rs)).
|
The `CI` workflow executes these tests on the stable rust toolchain (see [tools/ci](../../tools/ci/src/main.rs)).
|
||||||
|
|
||||||
|
For information on writing tests see [bevy_compile_test_utils/README.md](../bevy_compile_test_utils/README.md).
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let t = trybuild::TestCases::new();
|
|
||||||
t.compile_fail("tests/deref_derive/*.fail.rs");
|
|
||||||
t.pass("tests/deref_derive/*.pass.rs");
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
error: unexpected token in attribute
|
|
||||||
--> tests/deref_derive/invalid_attribute.fail.rs:6:34
|
|
||||||
|
|
|
||||||
6 | struct TupleStruct(usize, #[deref()] String);
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: unexpected token in attribute
|
|
||||||
--> tests/deref_derive/invalid_attribute.fail.rs:11:12
|
|
||||||
|
|
|
||||||
11 | #[deref()]
|
|
||||||
| ^
|
|
|
@ -3,13 +3,16 @@ use bevy_derive::Deref;
|
||||||
// Reason: `#[deref]` doesn't take any arguments
|
// Reason: `#[deref]` doesn't take any arguments
|
||||||
|
|
||||||
#[derive(Deref)]
|
#[derive(Deref)]
|
||||||
struct TupleStruct(usize, #[deref()] String);
|
struct TupleStruct(
|
||||||
|
usize,
|
||||||
|
#[deref()] String
|
||||||
|
//~^ ERROR: unexpected token
|
||||||
|
);
|
||||||
|
|
||||||
#[derive(Deref)]
|
#[derive(Deref)]
|
||||||
struct Struct {
|
struct Struct {
|
||||||
foo: usize,
|
foo: usize,
|
||||||
#[deref()]
|
#[deref()]
|
||||||
|
//~^ ERROR: unexpected token
|
||||||
bar: String,
|
bar: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
error: unexpected token in attribute
|
||||||
|
--> tests/deref_derive/invalid_attribute_fail.rs:8:12
|
||||||
|
|
|
||||||
|
8 | #[deref()] String
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: unexpected token in attribute
|
||||||
|
--> tests/deref_derive/invalid_attribute_fail.rs:15:12
|
||||||
|
|
|
||||||
|
15 | #[deref()]
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1,9 +0,0 @@
|
||||||
use bevy_derive::Deref;
|
|
||||||
|
|
||||||
#[derive(Deref)]
|
|
||||||
struct UnitStruct;
|
|
||||||
|
|
||||||
#[derive(Deref)]
|
|
||||||
enum Enum {}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
use bevy_derive::Deref;
|
||||||
|
|
||||||
|
#[derive(Deref)]
|
||||||
|
//~^ ERROR: cannot be derived on field-less structs
|
||||||
|
struct UnitStruct;
|
||||||
|
|
||||||
|
#[derive(Deref)]
|
||||||
|
//~^ ERROR: can only be derived on structs
|
||||||
|
enum Enum {}
|
|
@ -1,5 +1,5 @@
|
||||||
error: Deref cannot be derived on field-less structs
|
error: Deref cannot be derived on field-less structs
|
||||||
--> tests/deref_derive/invalid_item.fail.rs:3:10
|
--> tests/deref_derive/invalid_item_fail.rs:3:10
|
||||||
|
|
|
|
||||||
3 | #[derive(Deref)]
|
3 | #[derive(Deref)]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
@ -7,9 +7,12 @@ error: Deref cannot be derived on field-less structs
|
||||||
= note: this error originates in the derive macro `Deref` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Deref` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: Deref can only be derived on structs
|
error: Deref can only be derived on structs
|
||||||
--> tests/deref_derive/invalid_item.fail.rs:6:10
|
--> tests/deref_derive/invalid_item_fail.rs:7:10
|
||||||
|
|
|
|
||||||
6 | #[derive(Deref)]
|
7 | #[derive(Deref)]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `Deref` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Deref` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use bevy_derive::Deref;
|
use bevy_derive::Deref;
|
||||||
|
|
||||||
#[derive(Deref)]
|
#[derive(Deref)]
|
||||||
|
//~^ ERROR: requires one field to have
|
||||||
struct TupleStruct(usize, String);
|
struct TupleStruct(usize, String);
|
||||||
|
|
||||||
#[derive(Deref)]
|
#[derive(Deref)]
|
||||||
|
//~^ ERROR: requires one field to have
|
||||||
struct Struct {
|
struct Struct {
|
||||||
foo: usize,
|
foo: usize,
|
||||||
bar: String,
|
bar: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: deriving Deref on multi-field structs requires one field to have the `#[deref]` attribute
|
error: deriving Deref on multi-field structs requires one field to have the `#[deref]` attribute
|
||||||
--> tests/deref_derive/missing_attribute.fail.rs:3:10
|
--> tests/deref_derive/missing_attribute_fail.rs:3:10
|
||||||
|
|
|
|
||||||
3 | #[derive(Deref)]
|
3 | #[derive(Deref)]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
@ -7,9 +7,12 @@ error: deriving Deref on multi-field structs requires one field to have the `#[d
|
||||||
= note: this error originates in the derive macro `Deref` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Deref` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: deriving Deref on multi-field structs requires one field to have the `#[deref]` attribute
|
error: deriving Deref on multi-field structs requires one field to have the `#[deref]` attribute
|
||||||
--> tests/deref_derive/missing_attribute.fail.rs:6:10
|
--> tests/deref_derive/missing_attribute_fail.rs:7:10
|
||||||
|
|
|
|
||||||
6 | #[derive(Deref)]
|
7 | #[derive(Deref)]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `Deref` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `Deref` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
use bevy_derive::Deref;
|
|
||||||
|
|
||||||
#[derive(Deref)]
|
|
||||||
struct TupleStruct(#[deref] usize, #[deref] String);
|
|
||||||
|
|
||||||
#[derive(Deref)]
|
|
||||||
struct Struct {
|
|
||||||
#[deref]
|
|
||||||
foo: usize,
|
|
||||||
#[deref]
|
|
||||||
bar: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,11 +0,0 @@
|
||||||
error: `#[deref]` attribute can only be used on a single field
|
|
||||||
--> tests/deref_derive/multiple_attributes.fail.rs:4:36
|
|
||||||
|
|
|
||||||
4 | struct TupleStruct(#[deref] usize, #[deref] String);
|
|
||||||
| ^^^^^^^^
|
|
||||||
|
|
||||||
error: `#[deref]` attribute can only be used on a single field
|
|
||||||
--> tests/deref_derive/multiple_attributes.fail.rs:10:5
|
|
||||||
|
|
|
||||||
10 | #[deref]
|
|
||||||
| ^^^^^^^^
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
use bevy_derive::Deref;
|
||||||
|
|
||||||
|
#[derive(Deref)]
|
||||||
|
struct TupleStruct(
|
||||||
|
#[deref] usize,
|
||||||
|
#[deref] String
|
||||||
|
//~^ ERROR: can only be used on a single field
|
||||||
|
);
|
||||||
|
|
||||||
|
#[derive(Deref)]
|
||||||
|
struct Struct {
|
||||||
|
#[deref]
|
||||||
|
foo: usize,
|
||||||
|
#[deref]
|
||||||
|
//~^ ERROR: can only be used on a single field
|
||||||
|
bar: String,
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
error: `#[deref]` attribute can only be used on a single field
|
||||||
|
--> tests/deref_derive/multiple_attributes_fail.rs:6:5
|
||||||
|
|
|
||||||
|
6 | #[deref] String
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[deref]` attribute can only be used on a single field
|
||||||
|
--> tests/deref_derive/multiple_attributes_fail.rs:14:5
|
||||||
|
|
|
||||||
|
14 | #[deref]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//@check-pass
|
||||||
use bevy_derive::Deref;
|
use bevy_derive::Deref;
|
||||||
|
|
||||||
#[derive(Deref)]
|
#[derive(Deref)]
|
||||||
|
@ -17,6 +18,7 @@ struct Struct {
|
||||||
fn main() {
|
fn main() {
|
||||||
let value = TupleStruct(123, "Hello world!".to_string());
|
let value = TupleStruct(123, "Hello world!".to_string());
|
||||||
let _: &String = &*value;
|
let _: &String = &*value;
|
||||||
|
let _ = value.0;
|
||||||
|
|
||||||
let value = Struct {
|
let value = Struct {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -25,4 +27,5 @@ fn main() {
|
||||||
baz: 321,
|
baz: 321,
|
||||||
};
|
};
|
||||||
let _: &String = &*value;
|
let _: &String = &*value;
|
||||||
|
let _ = value.baz;
|
||||||
}
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
//@check-pass
|
||||||
use bevy_derive::Deref;
|
use bevy_derive::Deref;
|
||||||
|
|
||||||
#[derive(Deref)]
|
#[derive(Deref)]
|
|
@ -1,6 +0,0 @@
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let t = trybuild::TestCases::new();
|
|
||||||
t.compile_fail("tests/deref_mut_derive/*.fail.rs");
|
|
||||||
t.pass("tests/deref_mut_derive/*.pass.rs");
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
error: unexpected token in attribute
|
|
||||||
--> tests/deref_mut_derive/invalid_attribute.fail.rs:7:34
|
|
||||||
|
|
|
||||||
7 | struct TupleStruct(usize, #[deref()] String);
|
|
||||||
| ^
|
|
||||||
|
|
||||||
error: unexpected token in attribute
|
|
||||||
--> tests/deref_mut_derive/invalid_attribute.fail.rs:20:12
|
|
||||||
|
|
|
||||||
20 | #[deref()]
|
|
||||||
| ^
|
|
|
@ -4,7 +4,11 @@ use std::ops::Deref;
|
||||||
// Reason: `#[deref]` doesn't take any arguments
|
// Reason: `#[deref]` doesn't take any arguments
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
struct TupleStruct(usize, #[deref()] String);
|
struct TupleStruct(
|
||||||
|
usize,
|
||||||
|
#[deref()] String
|
||||||
|
//~^ ERROR: unexpected token
|
||||||
|
);
|
||||||
|
|
||||||
impl Deref for TupleStruct {
|
impl Deref for TupleStruct {
|
||||||
type Target = String;
|
type Target = String;
|
||||||
|
@ -18,6 +22,7 @@ impl Deref for TupleStruct {
|
||||||
struct Struct {
|
struct Struct {
|
||||||
foo: usize,
|
foo: usize,
|
||||||
#[deref()]
|
#[deref()]
|
||||||
|
//~^ ERROR: unexpected token
|
||||||
bar: String,
|
bar: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,5 +33,3 @@ impl Deref for Struct {
|
||||||
&self.bar
|
&self.bar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
error: unexpected token in attribute
|
||||||
|
--> tests/deref_mut_derive/invalid_attribute_fail.rs:9:12
|
||||||
|
|
|
||||||
|
9 | #[deref()] String
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: unexpected token in attribute
|
||||||
|
--> tests/deref_mut_derive/invalid_attribute_fail.rs:24:12
|
||||||
|
|
|
||||||
|
24 | #[deref()]
|
||||||
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use bevy_derive::DerefMut;
|
use bevy_derive::DerefMut;
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
|
//~^ ERROR: cannot be derived on field-less structs
|
||||||
struct UnitStruct;
|
struct UnitStruct;
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
|
//~^ ERROR: can only be derived on structs
|
||||||
enum Enum {}
|
enum Enum {}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: DerefMut cannot be derived on field-less structs
|
error: DerefMut cannot be derived on field-less structs
|
||||||
--> tests/deref_mut_derive/invalid_item.fail.rs:3:10
|
--> tests/deref_mut_derive/invalid_item_fail.rs:3:10
|
||||||
|
|
|
|
||||||
3 | #[derive(DerefMut)]
|
3 | #[derive(DerefMut)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
@ -7,9 +7,12 @@ error: DerefMut cannot be derived on field-less structs
|
||||||
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: DerefMut can only be derived on structs
|
error: DerefMut can only be derived on structs
|
||||||
--> tests/deref_mut_derive/invalid_item.fail.rs:6:10
|
--> tests/deref_mut_derive/invalid_item_fail.rs:7:10
|
||||||
|
|
|
|
||||||
6 | #[derive(DerefMut)]
|
7 | #[derive(DerefMut)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -2,6 +2,7 @@ use bevy_derive::DerefMut;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
|
//~^ E0308
|
||||||
struct TupleStruct(#[deref] usize, String);
|
struct TupleStruct(#[deref] usize, String);
|
||||||
|
|
||||||
impl Deref for TupleStruct {
|
impl Deref for TupleStruct {
|
||||||
|
@ -13,6 +14,7 @@ impl Deref for TupleStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
|
//~^ E0308
|
||||||
struct Struct {
|
struct Struct {
|
||||||
#[deref]
|
#[deref]
|
||||||
foo: usize,
|
foo: usize,
|
||||||
|
@ -26,5 +28,3 @@ impl Deref for Struct {
|
||||||
&self.bar
|
&self.bar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,5 +1,5 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> tests/deref_mut_derive/mismatched_target_type.fail.rs:4:10
|
--> tests/deref_mut_derive/mismatched_target_type_fail.rs:4:10
|
||||||
|
|
|
|
||||||
4 | #[derive(DerefMut)]
|
4 | #[derive(DerefMut)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
@ -12,9 +12,9 @@ error[E0308]: mismatched types
|
||||||
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> tests/deref_mut_derive/mismatched_target_type.fail.rs:15:10
|
--> tests/deref_mut_derive/mismatched_target_type_fail.rs:16:10
|
||||||
|
|
|
|
||||||
15 | #[derive(DerefMut)]
|
16 | #[derive(DerefMut)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
| |
|
| |
|
||||||
| expected `&mut String`, found `&mut usize`
|
| expected `&mut String`, found `&mut usize`
|
||||||
|
@ -23,3 +23,7 @@ error[E0308]: mismatched types
|
||||||
= note: expected mutable reference `&mut String`
|
= note: expected mutable reference `&mut String`
|
||||||
found mutable reference `&mut usize`
|
found mutable reference `&mut usize`
|
||||||
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
|
@ -2,6 +2,7 @@ use bevy_derive::DerefMut;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
|
//~^ ERROR: requires one field to have
|
||||||
struct TupleStruct(usize, String);
|
struct TupleStruct(usize, String);
|
||||||
|
|
||||||
impl Deref for TupleStruct {
|
impl Deref for TupleStruct {
|
||||||
|
@ -13,6 +14,7 @@ impl Deref for TupleStruct {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
|
//~^ ERROR: requires one field to have
|
||||||
struct Struct {
|
struct Struct {
|
||||||
foo: usize,
|
foo: usize,
|
||||||
bar: String,
|
bar: String,
|
||||||
|
@ -25,5 +27,3 @@ impl Deref for Struct {
|
||||||
&self.bar
|
&self.bar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: deriving DerefMut on multi-field structs requires one field to have the `#[deref]` attribute
|
error: deriving DerefMut on multi-field structs requires one field to have the `#[deref]` attribute
|
||||||
--> tests/deref_mut_derive/missing_attribute.fail.rs:4:10
|
--> tests/deref_mut_derive/missing_attribute_fail.rs:4:10
|
||||||
|
|
|
|
||||||
4 | #[derive(DerefMut)]
|
4 | #[derive(DerefMut)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
@ -7,9 +7,12 @@ error: deriving DerefMut on multi-field structs requires one field to have the `
|
||||||
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
error: deriving DerefMut on multi-field structs requires one field to have the `#[deref]` attribute
|
error: deriving DerefMut on multi-field structs requires one field to have the `#[deref]` attribute
|
||||||
--> tests/deref_mut_derive/missing_attribute.fail.rs:15:10
|
--> tests/deref_mut_derive/missing_attribute_fail.rs:16:10
|
||||||
|
|
|
|
||||||
15 | #[derive(DerefMut)]
|
16 | #[derive(DerefMut)]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1,13 +0,0 @@
|
||||||
use bevy_derive::DerefMut;
|
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
|
||||||
struct TupleStruct(usize, #[deref] String);
|
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
|
||||||
struct Struct {
|
|
||||||
foo: usize,
|
|
||||||
#[deref]
|
|
||||||
bar: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,33 +0,0 @@
|
||||||
error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied
|
|
||||||
--> tests/deref_mut_derive/missing_deref.fail.rs:4:8
|
|
||||||
|
|
|
||||||
4 | struct TupleStruct(usize, #[deref] String);
|
|
||||||
| ^^^^^^^^^^^ the trait `Deref` is not implemented for `TupleStruct`
|
|
||||||
|
|
|
||||||
note: required by a bound in `DerefMut`
|
|
||||||
--> $RUST/core/src/ops/deref.rs
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied
|
|
||||||
--> tests/deref_mut_derive/missing_deref.fail.rs:3:10
|
|
||||||
|
|
|
||||||
3 | #[derive(DerefMut)]
|
|
||||||
| ^^^^^^^^ the trait `Deref` is not implemented for `TupleStruct`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `Struct: Deref` is not satisfied
|
|
||||||
--> tests/deref_mut_derive/missing_deref.fail.rs:7:8
|
|
||||||
|
|
|
||||||
7 | struct Struct {
|
|
||||||
| ^^^^^^ the trait `Deref` is not implemented for `Struct`
|
|
||||||
|
|
|
||||||
note: required by a bound in `DerefMut`
|
|
||||||
--> $RUST/core/src/ops/deref.rs
|
|
||||||
|
|
||||||
error[E0277]: the trait bound `Struct: Deref` is not satisfied
|
|
||||||
--> tests/deref_mut_derive/missing_deref.fail.rs:6:10
|
|
||||||
|
|
|
||||||
6 | #[derive(DerefMut)]
|
|
||||||
| ^^^^^^^^ the trait `Deref` is not implemented for `Struct`
|
|
||||||
|
|
|
||||||
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// I'd love to check for E0277 errors here but we can't because
|
||||||
|
// the diagnostic contains a path to the system libraries which
|
||||||
|
// isn't consistent across systems.
|
||||||
|
|
||||||
|
use bevy_derive::DerefMut;
|
||||||
|
|
||||||
|
#[derive(DerefMut)]
|
||||||
|
//~^ ERROR: trait bound
|
||||||
|
struct TupleStruct(usize, #[deref] String);
|
||||||
|
//~^ ERROR: trait bound
|
||||||
|
|
||||||
|
#[derive(DerefMut)]
|
||||||
|
//~^ ERROR: trait bound
|
||||||
|
struct Struct {
|
||||||
|
//~^ ERROR: trait bound
|
||||||
|
foo: usize,
|
||||||
|
#[deref]
|
||||||
|
bar: String,
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied
|
||||||
|
--> tests/deref_mut_derive/missing_deref_fail.rs:10:8
|
||||||
|
|
|
||||||
|
10 | struct TupleStruct(usize, #[deref] String);
|
||||||
|
| ^^^^^^^^^^^ the trait `Deref` is not implemented for `TupleStruct`
|
||||||
|
|
|
||||||
|
note: required by a bound in `DerefMut`
|
||||||
|
--> $RUSTUP_HOME/.rustup/toolchains/stable-x86_64-pc-windows-msvc/lib/rustlib/src/rust/library/core/src/ops/deref.rs:264:21
|
||||||
|
|
|
||||||
|
264 | pub trait DerefMut: Deref {
|
||||||
|
| ^^^^^ required by this bound in `DerefMut`
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `TupleStruct: Deref` is not satisfied
|
||||||
|
--> tests/deref_mut_derive/missing_deref_fail.rs:7:10
|
||||||
|
|
|
||||||
|
7 | #[derive(DerefMut)]
|
||||||
|
| ^^^^^^^^ the trait `Deref` is not implemented for `TupleStruct`
|
||||||
|
|
|
||||||
|
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Struct: Deref` is not satisfied
|
||||||
|
--> tests/deref_mut_derive/missing_deref_fail.rs:15:8
|
||||||
|
|
|
||||||
|
15 | struct Struct {
|
||||||
|
| ^^^^^^ the trait `Deref` is not implemented for `Struct`
|
||||||
|
|
|
||||||
|
note: required by a bound in `DerefMut`
|
||||||
|
--> $RUSTUP_HOME/.rustup/toolchains/stable-x86_64-pc-windows-msvc/lib/rustlib/src/rust/library/core/src/ops/deref.rs:264:21
|
||||||
|
|
|
||||||
|
264 | pub trait DerefMut: Deref {
|
||||||
|
| ^^^^^ required by this bound in `DerefMut`
|
||||||
|
|
||||||
|
error[E0277]: the trait bound `Struct: Deref` is not satisfied
|
||||||
|
--> tests/deref_mut_derive/missing_deref_fail.rs:13:10
|
||||||
|
|
|
||||||
|
13 | #[derive(DerefMut)]
|
||||||
|
| ^^^^^^^^ the trait `Deref` is not implemented for `Struct`
|
||||||
|
|
|
||||||
|
= note: this error originates in the derive macro `DerefMut` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0277`.
|
|
@ -1,11 +0,0 @@
|
||||||
error: `#[deref]` attribute can only be used on a single field
|
|
||||||
--> tests/deref_mut_derive/multiple_attributes.fail.rs:5:36
|
|
||||||
|
|
|
||||||
5 | struct TupleStruct(#[deref] usize, #[deref] String);
|
|
||||||
| ^^^^^^^^
|
|
||||||
|
|
||||||
error: `#[deref]` attribute can only be used on a single field
|
|
||||||
--> tests/deref_mut_derive/multiple_attributes.fail.rs:19:5
|
|
||||||
|
|
|
||||||
19 | #[deref]
|
|
||||||
| ^^^^^^^^
|
|
|
@ -2,7 +2,11 @@ use bevy_derive::DerefMut;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
struct TupleStruct(#[deref] usize, #[deref] String);
|
struct TupleStruct(
|
||||||
|
#[deref] usize,
|
||||||
|
#[deref] String
|
||||||
|
//~^ ERROR: can only be used on a single field
|
||||||
|
);
|
||||||
|
|
||||||
impl Deref for TupleStruct {
|
impl Deref for TupleStruct {
|
||||||
type Target = String;
|
type Target = String;
|
||||||
|
@ -17,6 +21,7 @@ struct Struct {
|
||||||
#[deref]
|
#[deref]
|
||||||
foo: usize,
|
foo: usize,
|
||||||
#[deref]
|
#[deref]
|
||||||
|
//~^ ERROR: can only be used on a single field
|
||||||
bar: String,
|
bar: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,5 +32,3 @@ impl Deref for Struct {
|
||||||
&self.bar
|
&self.bar
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
error: `#[deref]` attribute can only be used on a single field
|
||||||
|
--> tests/deref_mut_derive/multiple_attributes_fail.rs:7:5
|
||||||
|
|
|
||||||
|
7 | #[deref] String
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: `#[deref]` attribute can only be used on a single field
|
||||||
|
--> tests/deref_mut_derive/multiple_attributes_fail.rs:23:5
|
||||||
|
|
|
||||||
|
23 | #[deref]
|
||||||
|
| ^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
|
//@check-pass
|
||||||
|
|
||||||
use bevy_derive::DerefMut;
|
use bevy_derive::DerefMut;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
struct TupleStruct(usize, #[deref] String);
|
// The first field is never read, but we want it there to check that the derive skips it.
|
||||||
|
struct TupleStruct(#[allow(dead_code)] usize, #[deref] String);
|
||||||
|
|
||||||
impl Deref for TupleStruct {
|
impl Deref for TupleStruct {
|
||||||
type Target = String;
|
type Target = String;
|
||||||
|
@ -14,6 +17,8 @@ impl Deref for TupleStruct {
|
||||||
|
|
||||||
#[derive(DerefMut)]
|
#[derive(DerefMut)]
|
||||||
struct Struct {
|
struct Struct {
|
||||||
|
#[allow(dead_code)]
|
||||||
|
// Same justification as above.
|
||||||
foo: usize,
|
foo: usize,
|
||||||
#[deref]
|
#[deref]
|
||||||
bar: String,
|
bar: String,
|
|
@ -1,3 +1,4 @@
|
||||||
|
//@check-pass
|
||||||
use bevy_derive::DerefMut;
|
use bevy_derive::DerefMut;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
4
crates/bevy_macros_compile_fail_tests/tests/derive.rs
Normal file
4
crates/bevy_macros_compile_fail_tests/tests/derive.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
fn main() -> bevy_compile_test_utils::ui_test::Result<()> {
|
||||||
|
bevy_compile_test_utils::test_multiple(["tests/deref_derive", "tests/deref_mut_derive"])
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,13 @@ repository = "https://github.com/bevyengine/bevy"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# ui_test dies if we don't specify the version. See oli-obk/ui_test#211
|
||||||
|
bevy_reflect = { path = "../bevy_reflect", version = "0.14.0-dev" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
bevy_reflect = { path = "../bevy_reflect" }
|
bevy_compile_test_utils = { path = "../bevy_compile_test_utils" }
|
||||||
trybuild = "1.0.71"
|
|
||||||
|
[[test]]
|
||||||
|
name = "derive"
|
||||||
|
harness = false
|
||||||
|
|
|
@ -5,3 +5,5 @@ Bevy.
|
||||||
The tests assert on the exact compiler errors and can easily fail for new Rust versions due to updated compiler errors (e.g. changes in spans).
|
The tests assert on the exact compiler errors and can easily fail for new Rust versions due to updated compiler errors (e.g. changes in spans).
|
||||||
|
|
||||||
The `CI` workflow executes these tests on the stable rust toolchain (see [tools/ci](../../tools/ci/src/main.rs)).
|
The `CI` workflow executes these tests on the stable rust toolchain (see [tools/ci](../../tools/ci/src/main.rs)).
|
||||||
|
|
||||||
|
For information on writing tests see [bevy_compile_test_utils/README.md](../bevy_compile_test_utils/README.md).
|
||||||
|
|
3
crates/bevy_reflect_compile_fail_tests/tests/derive.rs
Normal file
3
crates/bevy_reflect_compile_fail_tests/tests/derive.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
fn main() -> bevy_compile_test_utils::ui_test::Result<()> {
|
||||||
|
bevy_compile_test_utils::test("tests/reflect_derive")
|
||||||
|
}
|
|
@ -1,6 +0,0 @@
|
||||||
#[test]
|
|
||||||
fn test() {
|
|
||||||
let t = trybuild::TestCases::new();
|
|
||||||
t.compile_fail("tests/reflect_derive/*.fail.rs");
|
|
||||||
t.pass("tests/reflect_derive/*.pass.rs");
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
//@check-pass
|
||||||
use bevy_reflect::prelude::*;
|
use bevy_reflect::prelude::*;
|
||||||
|
|
||||||
fn main() {}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct NonReflect;
|
struct NonReflect;
|
||||||
|
|
|
@ -13,10 +13,10 @@ impl<T> FromType<T> for ReflectMyTrait {
|
||||||
// Reason: populated `where` clause must be last with #[reflect(MyTrait)]
|
// Reason: populated `where` clause must be last with #[reflect(MyTrait)]
|
||||||
#[derive(Reflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(where T: std::fmt::Debug, MyTrait)]
|
#[reflect(where T: std::fmt::Debug, MyTrait)]
|
||||||
|
//~^ ERROR: /expected.+:/
|
||||||
|
// TODO: Investigate a way to improve the error message.
|
||||||
pub struct Foo<T> {
|
pub struct Foo<T> {
|
||||||
value: String,
|
value: String,
|
||||||
#[reflect(ignore)]
|
#[reflect(ignore)]
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,5 +1,8 @@
|
||||||
error: expected `:`
|
error: expected `:`
|
||||||
--> tests/reflect_derive/custom_where.fail.rs:15:44
|
--> tests/reflect_derive/custom_where_fail.rs:15:44
|
||||||
|
|
|
|
||||||
15 | #[reflect(where T: std::fmt::Debug, MyTrait)]
|
15 | #[reflect(where T: std::fmt::Debug, MyTrait)]
|
||||||
| ^
|
| ^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
//@check-pass
|
||||||
use bevy_reflect::{FromType, Reflect};
|
use bevy_reflect::{FromType, Reflect};
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
|
@ -34,5 +35,3 @@ pub struct Baz<T> {
|
||||||
#[reflect(ignore)]
|
#[reflect(ignore)]
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -4,6 +4,7 @@ use bevy_reflect::{FromReflect, Reflect};
|
||||||
#[derive(Reflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = false)]
|
#[reflect(from_reflect = false)]
|
||||||
#[reflect(from_reflect = true)]
|
#[reflect(from_reflect = true)]
|
||||||
|
//~^ ERROR: already set to false
|
||||||
struct Foo {
|
struct Foo {
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
|
@ -12,14 +13,14 @@ struct Foo {
|
||||||
#[derive(Reflect)]
|
#[derive(Reflect)]
|
||||||
#[reflect(from_reflect = true)]
|
#[reflect(from_reflect = true)]
|
||||||
#[reflect(from_reflect = false)]
|
#[reflect(from_reflect = false)]
|
||||||
|
//~^ ERROR: already set to true
|
||||||
struct Bar {
|
struct Bar {
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reason: Conflicting `FromReflect` implementations
|
// Reason: Conflicting `FromReflect` implementations
|
||||||
#[derive(Reflect, FromReflect)]
|
#[derive(Reflect, FromReflect)]
|
||||||
|
//~^ ERROR: conflicting implementation
|
||||||
struct Baz {
|
struct Baz {
|
||||||
value: String,
|
value: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {}
|
|
|
@ -1,21 +1,25 @@
|
||||||
error: `from_reflect` already set to false
|
error: `from_reflect` already set to false
|
||||||
--> tests/reflect_derive/from_reflect.fail.rs:6:26
|
--> tests/reflect_derive/from_reflect_fail.rs:6:26
|
||||||
|
|
|
|
||||||
6 | #[reflect(from_reflect = true)]
|
6 | #[reflect(from_reflect = true)]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: `from_reflect` already set to true
|
error: `from_reflect` already set to true
|
||||||
--> tests/reflect_derive/from_reflect.fail.rs:14:26
|
--> tests/reflect_derive/from_reflect_fail.rs:15:26
|
||||||
|
|
|
|
||||||
14 | #[reflect(from_reflect = false)]
|
15 | #[reflect(from_reflect = false)]
|
||||||
| ^^^^^
|
| ^^^^^
|
||||||
|
|
||||||
error[E0119]: conflicting implementations of trait `FromReflect` for type `Baz`
|
error[E0119]: conflicting implementations of trait `FromReflect` for type `Baz`
|
||||||
--> tests/reflect_derive/from_reflect.fail.rs:20:19
|
--> tests/reflect_derive/from_reflect_fail.rs:22:19
|
||||||
|
|
|
|
||||||
20 | #[derive(Reflect, FromReflect)]
|
22 | #[derive(Reflect, FromReflect)]
|
||||||
| ------- ^^^^^^^^^^^ conflicting implementation for `Baz`
|
| ------- ^^^^^^^^^^^ conflicting implementation for `Baz`
|
||||||
| |
|
| |
|
||||||
| first implementation here
|
| first implementation here
|
||||||
|
|
|
|
||||||
= note: this error originates in the derive macro `FromReflect` (in Nightly builds, run with -Z macro-backtrace for more info)
|
= note: this error originates in the derive macro `FromReflect` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0119`.
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue