Commit Graph

396 Commits

Author SHA1 Message Date
Nicholas Nethercote
b8072864aa
Streamline GetOwnership/FromArg/IntoReturn (#20126)
# Objective

Three impls are generated for each of these traits when the
`reflect_functions` feature is enabled.

Helps with #19873.

## Solution

Two of the three (the `&T` and `&mut T` ones) can be avoided by instead
providing blanket impls. The impl for `T` remains.

## Testing

I checked the output via `cargo expand`.

According to `-Zmacro-stats`, the size of the `Reflect` code generate
for `bevy_ui` drops by 10.4%.
2025-07-14 21:57:34 +00:00
Rob Parrett
2342e993ec
Bump typos to 1.34.0 (#20013)
# Objective

Closes #20006

## Solution

Bump `typos` and also fix the new typos detected

## Testing

CI
2025-07-07 20:15:06 +00:00
Nicholas Nethercote
d80078cf2d
bevy_reflect: Introduce reflect_clone_and_take. (#19944)
# Objective

There is a pattern that appears in multiple places, involving
`reflect_clone`, followed by `take`, followed by `map_err` that produces
a `FailedDowncast` in a particular form.

## Solution

Introduces `reflect_clone_and_take`, which factors out the repeated
code.

## Testing

`cargo run -p ci`

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-07-07 19:57:29 +00:00
Nicholas Nethercote
f1df61e458
bevy_reflect: Avoid trait bounds on non-generic types (#19929)
# Objective

All the derived reflection methods currently have multiple trait bounds
on non-generic field types, which serve no purpose. The are emitted
because "emit bounds on all fields" is easier than "emit bounds on
fields that need them". But improving things isn't too hard.

Similarly, lots of useless `Any + Send + Sync` bounds exist on
non-generic types.

Helps a lot with #19873.

## Solution

Remove the unnecessary bounds by only emitting them if the relevant type
is generic.

## Testing

I used `cargo expand` to confirm the unnecessary bounds are no longer
produced.

`-Zmacro-stats` output tells me this reduces the size of the `Reflect`
code produced for `bevy_ui` by 21.2%.
2025-07-07 19:53:14 +00:00
Alix Bott
dd4479ed30
Fix PartialReflect::apply for maps, remove get_at/_mut from Map trait (#19802)
# Objective

- Fixes https://github.com/bevyengine/bevy/issues/14328
- `DynamicMap::drain` was broken (indices weren't cleared, causing a
panic when reading later)
- `PartialReflect::apply` was broken for maps and sets, because they
don't remove entries from the `self` map that aren't in the applied map.
- I discovered this bug when implementing MapEntities on a Component
containing a `HashMap<Entity, _>`. Because `apply` is used to reapply
the changes to the reflected map, the map ended up littered with a ton
of outdated entries.

## Solution

- Remove the separate `Vec` in `DynamicMap` and use the `HashTable`
directly, like it is in `DynamicSet`.
- Replace `MapIter` by `Box<dyn Iterator>` (like for `DynamicSet`), and
`Map::get_at` and `Map::get_at_mut` which are now unused.
- Now assume `DynamicMap` types are unordered and adjust documentation
accordingly.
- Fix documentation of `DynamicSet` (ordered -> unordered)
- Added `Map::retain` and `Set::retain`, and use them to remove excess
entries in `PartialReflect::apply` implementations.

## Testing

- Added `map::tests::apply` and `set::tests::apply` to validate
`<DynamicMap as PartialReflect>::apply` and `<DynamicSet as
PartialReflect>::apply`
2025-06-25 15:42:01 +00:00
Rob Parrett
d3ad66f033
Fix some typos (#19788)
# Objective

- Notice a word duplication typo
- Small quest to fix similar or nearby typos with my faithful companion
`\b(\w+)\s+\1\b`

## Solution

Fix em
2025-06-23 22:32:46 +00:00
theotherphil
7645ce91ed
Add newlines before impl blocks (#19746)
# Objective

Fix https://github.com/bevyengine/bevy/issues/19617 

# Solution

Add newlines before all impl blocks.

I suspect that at least some of these will be objectionable! If there's
a desired Bevy style for this then I'll update the PR. If not then we
can just close it - it's the work of a single find and replace.
2025-06-22 23:07:02 +00:00
Erick Z
20781371e8
Register ReflectSerialize for &'static str (#19680)
# Objective

- When trying to serialize an structure that contains `&'static str`
using only Reflection, I get the following error:
```
"type `&str` did not register the `ReflectSerialize` or `ReflectSerializeWithRegistry` type data. 
For certain types, this may need to be registered manually using `register_type_data` (stack: ... -> `core::option::Option<&str>` -> `&str`)")
```
## Solution

- Register `ReflectSerialize` for `&str`

## Testing

- `cargo run -p ci`: OK
2025-06-16 22:09:15 +00:00
theotherphil
3b25b38bdc
deny(missing_docs) for bevy_reflect (#19481)
## Objective

Deny missing docs in bevy_reflect, towards
https://github.com/bevyengine/bevy/issues/3492.

## Solution

Add the missing docs!

## Testing

N/A
2025-06-16 21:26:24 +00:00
andriyDev
f47b1c00ee
Bump ron version to 0.10. (#19631)
# Objective

- Update ron to the latest version.
- This is blocking changes to AnimationGraph (as some valid structs are
not capable of being deserialized).

## Solution

- Bump ron!

## Testing

- The particular issue I was blocked by seems to be resolved!
2025-06-13 19:54:31 +00:00
Carter Anderson
7e9d6d852b
bevyengine.org -> bevy.org (#19503)
We have acquired [bevy.org](https://bevy.org) and the migration has
finished! Meaning we can now update all of the references in this repo.
2025-06-05 23:09:28 +00:00
theotherphil
3d7486b019
Clarify PartialReflect::apply docs (#19250)
# Objective

Fix https://github.com/bevyengine/bevy/issues/18558

## Solution

* Replace `T` in docs with `Self`
* Fix broken link - replace "introspection subtraits" with "reflection
subtraits"
* Added missing `Set` variant to the list of per-`ReflectKind`-variation
behaviours

## Testing

cargo doc --serve locally to check that the broken link is fixed

---------

Co-authored-by: Gino Valente <49806985+MrGVSV@users.noreply.github.com>
2025-06-02 22:12:16 +00:00
SpecificProtagonist
a266e7e642
More uninlined_format_args fixes (#19396)
# Objective

There are several uninlined format args (seems to be in more formatting
macros and in more crates) that are not detected on stable, but are on
nightly.

## Solution

Fix them.
2025-05-28 02:35:18 +00:00
Gino Valente
1674938c49
bevy_reflect: Split up the std module (#18939)
> [!important]
> To **maintainers**: we should wait to merge this one in until after
#18944 lands so that cherry-picking the latter for 0.16.1 is simpler.

# Objective

The `std` module is where we implement the reflection traits for types
that are exported from `std` (including `core` and `alloc`). Over time,
this file has grown increasingly large, making it difficult to navigate
and a pain point for merge conflicts.

The goal of this PR is to break up the module into smaller chunks.

## Solution

The `std` module has been split into many submodules:
- `alloc`
- `bevy_platform`
- `core`
- `std`

Each of these new modules is comprised of submodules that closely
resemble the actual module. For example, the impls for
`::alloc::vec::Vec` have been moved to
`bevy_reflect::impls::alloc::vec::Vec`.

Some liberties were taken. For example, `Cow<'static, Path>` was kept in
`bevy_reflect::impls::std::path` rather than
`bevy_reflect::impls::alloc::borrow`.

You may ask: _Isn't this a little overkill? Why does the one-line impl
for `TypeId` need its own file?_

And yes, it is partly overkill. But the benefit with this approach is
that where an `std`-related type should live is mostly unambiguous. If
we wanted to reflect `::core::net::Ipv4Addr`, it's very clear that it
should be done in `bevy_reflect::impls::core::net`.

We can discuss better ways of breaking this up if people have other
ideas or opinions, but I think this is a pretty straightforward way of
doing it.

### Note to Reviewers

The code is pretty much copy-paste from the mega module to the new
submodules. It's probably best to focus efforts on reviewing the general
module structure, as well as maybe which impls are included where.

You _can_ review the code contained within each impl, but I promise you
the only thing I touched were the paths in the macros so they could be
more hygienic :)

## Testing

You can just check that everything compiles still:

```
cargo check -p bevy_reflect --tests
```
2025-05-26 19:10:47 +00:00
Zachary Harrold
63e78fe489
Deprecated Begone! 0.16 Cleanup (#19108)
# Objective

A fair few items were deprecated in 0.16. Let's delete them now that
we're in the 0.17 development cycle!

## Solution

- Deleted items marked deprecated in 0.16.

## Testing

- CI

---

## Notes

I'm making the assumption that _everything_ deprecated in 0.16 should be
removed in 0.17. That may be a false assumption in certain cases. Please
check the items to be removed to see if there are any exceptions we
should keep around for another cycle!
2025-05-07 18:17:41 +00:00
tmstorey
c55c69e3fc
Add NonNilUuid support to bevy_reflect (#18604)
# Objective

- If using a `NonNilUuid` in Bevy, it's difficult to reflect it.

## Solution

- Adds `NonNilUuid` using `impl_reflect_opaque!`.

## Testing

- Built with no issues found locally.
- Essentially the same as the `Uuid` support except without `Default`.

Co-authored-by: TM Storey <mail@tmstorey.id.au>
2025-05-04 08:22:57 +00:00
Gino Valente
31e9a3c411
bevy_reflect: Re-reflect hashbrown types (#18944)
# Objective

Fixes #18943

## Solution

Reintroduces support for `hashbrown`'s `HashMap` and `HashSet` types.
These were inadvertently removed when `bevy_platform` newtyped the
`hashbrown` types.

Since we removed our `hashbrown` dependency, I gated these impls behind
a `hashbrown` feature. Not entirely sure if this is necessary since we
enabled it for `bevy_reflect` through `bevy_platform` anyways. (Complex
features still confuse me a bit so let me know if I can just remove it!)

I also went ahead and preemptively implemented `TypePath` for `PassHash`
while I was here.

## Testing

You can test that it works by adding the following to a Bevy example
based on this PR (you'll also need to include `hashbrown` of course):

```rust
#[derive(Reflect)]
struct Foo(hashbrown::HashMap<String, String>);
```

Then check it compiles with:

```
cargo check --example hello_world --no-default-features --features=bevy_reflect/hashbrown
```
2025-04-28 19:26:53 +00:00
Carter Anderson
e9a0ef49f9
Rename bevy_platform_support to bevy_platform (#18813)
# Objective

The goal of `bevy_platform_support` is to provide a set of platform
agnostic APIs, alongside platform-specific functionality. This is a high
traffic crate (providing things like HashMap and Instant). Especially in
light of https://github.com/bevyengine/bevy/discussions/18799, it
deserves a friendlier / shorter name.

Given that it hasn't had a full release yet, getting this change in
before Bevy 0.16 makes sense.

## Solution

- Rename `bevy_platform_support` to `bevy_platform`.
2025-04-11 23:13:28 +00:00
person93
989b360fec
Add accessors to DynamicEnum for the DynamicVariant (#18693)
# Objective

- Closes https://github.com/bevyengine/bevy/issues/18692

## Solution

Add the methods as described
```rust
impl DynamicEnum {
    fn variant(&self) -> &DynamicVariant;
    fn variant_mut(&mut self) -> &mut DynamicVariant;
}
```
2025-04-05 02:33:00 +00:00
Lucas Franca
78d5c50b50
Add PartialEq and Hash reflections for AnimationNodeIndex (#18718)
# Objective

Fixes #18701

## Solution

Add reflection of `PartialEq` and `Hash` to `AnimationNodeIndex`

## Testing

Added a new `#[test]` with the minimal reproduction posted on #18701.
2025-04-04 16:35:12 +00:00
Periwink
bd00c915ec
add reflect for SocketAddr (#18676) 2025-04-03 03:51:20 +00:00
Gino Valente
f4716034fa
bevy_reflect: Fix TypePath string concatenation (#18609)
# Objective

Fixes #18606

When a type implements `Add` for `String`, the compiler can get confused
when attempting to add a `&String` to a `String`.

Unfortunately, this seems to be [expected
behavior](https://github.com/rust-lang/rust/issues/77143#issuecomment-698369286)
which causes problems for generic types since the current `TypePath`
derive generates code that appends strings in this manner.

## Solution

Explicitly use the `Add<&str>` implementation in the `TypePath` derive
macro.

## Testing

You can test locally by running:

```
cargo check -p bevy_reflect --tests
```
2025-03-29 21:01:53 +00:00
Kristoffer Søholm
7a37c4a109
Update bincode to 2.0 (#18396)
# Objective

Update bincode

## Solution

Fix compilation for #18352 by reading the [migration
guide](https://github.com/bincode-org/bincode/blob/trunk/docs/migration_guide.md)

Also fixes an unused import warning I got when running the tests for
bevy_reflect.
2025-03-25 04:09:46 +00:00
Wuketuke
5c3368fbcf
Fixed Reflect derive macro on empty enums (#18277) (#18298)
obtaining a reference to an empty enum is not possible in Rust, so I
just replaced any match on self with an `unreachable!()`
I checked if an enum is empty by checking if the `variant_patterns` vec
of the `EnumVariantOutputData` struct is empty
Fixes #18277

## Testing

I added one new unit test.
``` rust
#[test]
fn should_allow_empty_enums() {
    #[derive(Reflect)]
    enum Empty {}

    assert_impl_all!(Empty: Reflect);
}
```
2025-03-17 18:13:55 +00:00
Gino Valente
c2854a2a05
bevy_reflect: Deprecate PartialReflect::clone_value (#18284)
# Objective

#13432 added proper reflection-based cloning. This is a better method
than cloning via `clone_value` for reasons detailed in the description
of that PR. However, it may not be immediately apparent to users why one
should be used over the other, and what the gotchas of `clone_value`
are.

## Solution

This PR marks `PartialReflect::clone_value` as deprecated, with the
deprecation notice pointing users to `PartialReflect::reflect_clone`.
However, it also suggests using a new method introduced in this PR:
`PartialReflect::to_dynamic`.

`PartialReflect::to_dynamic` is essentially a renaming of
`PartialReflect::clone_value`. By naming it `to_dynamic`, we make it
very obvious that what's returned is a dynamic type. The one caveat to
this is that opaque types still use `reflect_clone` as they have no
corresponding dynamic type.

Along with changing the name, the method is now optional, and comes with
a default implementation that calls out to the respective reflection
subtrait method. This was done because there was really no reason to
require manual implementors provide a method that almost always calls
out to a known set of methods.

Lastly, to make this default implementation work, this PR also did a
similar thing with the `clone_dynamic ` methods on the reflection
subtraits. For example, `Struct::clone_dynamic` has been marked
deprecated and is superseded by `Struct::to_dynamic_struct`. This was
necessary to avoid the "multiple names in scope" issue.

### Open Questions

This PR maintains the original signature of `clone_value` on
`to_dynamic`. That is, it takes `&self` and returns `Box<dyn
PartialReflect>`.

However, in order for this to work, it introduces a panic if the value
is opaque and doesn't override the default `reflect_clone`
implementation.

One thing we could do to avoid the panic would be to make the conversion
fallible, either returning `Option<Box<dyn PartialReflect>>` or
`Result<Box<dyn PartialReflect>, ReflectCloneError>`.

This makes using the method a little more involved (i.e. users have to
either unwrap or handle the rare possibility of an error), but it would
set us up for a world where opaque types don't strictly need to be
`Clone`. Right now this bound is sort of implied by the fact that
`clone_value` is a required trait method, and the default behavior of
the macro is to use `Clone` for opaque types.

Alternatively, we could keep the signature but make the method required.
This maintains that implied bound where manual implementors must provide
some way of cloning the value (or YOLO it and just panic), but also
makes the API simpler to use.

Finally, we could just leave it with the panic. It's unlikely this would
occur in practice since our macro still requires `Clone` for opaque
types, and thus this would only ever be an issue if someone were to
manually implement `PartialReflect` without a valid `to_dynamic` or
`reflect_clone` method.

## Testing

You can test locally using the following command:

```
cargo test --package bevy_reflect --all-features
```

---

## Migration Guide

`PartialReflect::clone_value` is being deprecated. Instead, use
`PartialReflect::to_dynamic` if wanting to create a new dynamic instance
of the reflected value. Alternatively, use
`PartialReflect::reflect_clone` to attempt to create a true clone of the
underlying value.

Similarly, the following methods have been deprecated and should be
replaced with these alternatives:
- `Array::clone_dynamic` → `Array::to_dynamic_array`
- `Enum::clone_dynamic` → `Enum::to_dynamic_enum`
- `List::clone_dynamic` → `List::to_dynamic_list`
- `Map::clone_dynamic` → `Map::to_dynamic_map`
- `Set::clone_dynamic` → `Set::to_dynamic_set`
- `Struct::clone_dynamic` → `Struct::to_dynamic_struct`
- `Tuple::clone_dynamic` → `Tuple::to_dynamic_tuple`
- `TupleStruct::clone_dynamic` → `TupleStruct::to_dynamic_tuple_struct`
2025-03-14 19:33:57 +00:00
Gino Valente
f5210c54d2
bevy_reflect: Reflection-based cloning (#13432)
# Objective

Using `Reflect::clone_value` can be somewhat confusing to those
unfamiliar with how Bevy's reflection crate works. For example take the
following code:

```rust
let value: usize = 123;
let clone: Box<dyn Reflect> = value.clone_value();
```

What can we expect to be the underlying type of `clone`? If you guessed
`usize`, then you're correct! Let's try another:

```rust
#[derive(Reflect, Clone)]
struct Foo(usize);

let value: Foo = Foo(123);
let clone: Box<dyn Reflect> = value.clone_value();
```

What about this code? What is the underlying type of `clone`? If you
guessed `Foo`, unfortunately you'd be wrong. It's actually
`DynamicStruct`.

It's not obvious that the generated `Reflect` impl actually calls
`Struct::clone_dynamic` under the hood, which always returns
`DynamicStruct`.

There are already some efforts to make this a bit more apparent to the
end-user: #7207 changes the signature of `Reflect::clone_value` to
instead return `Box<dyn PartialReflect>`, signaling that we're
potentially returning a dynamic type.

But why _can't_ we return `Foo`?

`Foo` can obviously be cloned— in fact, we already derived `Clone` on
it. But even without the derive, this seems like something `Reflect`
should be able to handle. Almost all types that implement `Reflect`
either contain no data (trivially clonable), they contain a
`#[reflect_value]` type (which, by definition, must implement `Clone`),
or they contain another `Reflect` type (which recursively fall into one
of these three categories).

This PR aims to enable true reflection-based cloning where you get back
exactly the type that you think you do.

## Solution

Add a `Reflect::reflect_clone` method which returns `Result<Box<dyn
Reflect>, ReflectCloneError>`, where the `Box<dyn Reflect>` is
guaranteed to be the same type as `Self`.

```rust
#[derive(Reflect)]
struct Foo(usize);

let value: Foo = Foo(123);
let clone: Box<dyn Reflect> = value.reflect_clone().unwrap();
assert!(clone.is::<Foo>());
```

Notice that we didn't even need to derive `Clone` for this to work: it's
entirely powered via reflection!

Under the hood, the macro generates something like this:

```rust
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
    Ok(Box::new(Self {
        // The `reflect_clone` impl for `usize` just makes use of its `Clone` impl
        0: Reflect::reflect_clone(&self.0)?.take().map_err(/* ... */)?,
    }))
}
```

If we did derive `Clone`, we can tell `Reflect` to rely on that instead:

```rust
#[derive(Reflect, Clone)]
#[reflect(Clone)]
struct Foo(usize);
```

<details>
<summary>Generated Code</summary>

```rust
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
    Ok(Box::new(Clone::clone(self)))
}
```

</details>

Or, we can specify our own cloning function:

```rust
#[derive(Reflect)]
#[reflect(Clone(incremental_clone))]
struct Foo(usize);

fn incremental_clone(value: &usize) -> usize {
  *value + 1
}
```

<details>
<summary>Generated Code</summary>

```rust
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
    Ok(Box::new(incremental_clone(self)))
}
```

</details>

Similarly, we can specify how fields should be cloned. This is important
for fields that are `#[reflect(ignore)]`'d as we otherwise have no way
to know how they should be cloned.

```rust
#[derive(Reflect)]
struct Foo {
 #[reflect(ignore, clone)]
  bar: usize,
  #[reflect(ignore, clone = "incremental_clone")]
  baz: usize,
}

fn incremental_clone(value: &usize) -> usize {
  *value + 1
}
```

<details>
<summary>Generated Code</summary>

```rust
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError> {
    Ok(Box::new(Self {
        bar: Clone::clone(&self.bar),
        baz: incremental_clone(&self.baz),
    }))
}
```

</details>

If we don't supply a `clone` attribute for an ignored field, then the
method will automatically return
`Err(ReflectCloneError::FieldNotClonable {/* ... */})`.

`Err` values "bubble up" to the caller. So if `Foo` contains `Bar` and
the `reflect_clone` method for `Bar` returns `Err`, then the
`reflect_clone` method for `Foo` also returns `Err`.

### Attribute Syntax

You might have noticed the differing syntax between the container
attribute and the field attribute.

This was purely done for consistency with the current attributes. There
are PRs aimed at improving this. #7317 aims at making the
"special-cased" attributes more in line with the field attributes
syntactically. And #9323 aims at moving away from the stringified paths
in favor of just raw function paths.

### Compatibility with Unique Reflect

This PR was designed with Unique Reflect (#7207) in mind. This method
actually wouldn't change that much (if at all) under Unique Reflect. It
would still exist on `Reflect` and it would still `Option<Box<dyn
Reflect>>`. In fact, Unique Reflect would only _improve_ the user's
understanding of what this method returns.

We may consider moving what's currently `Reflect::clone_value` to
`PartialReflect` and possibly renaming it to `partial_reflect_clone` or
`clone_dynamic` to better indicate how it differs from `reflect_clone`.

## Testing

You can test locally by running the following command:

```
cargo test --package bevy_reflect
```

---

## Changelog

- Added `Reflect::reflect_clone` method
- Added `ReflectCloneError` error enum
- Added `#[reflect(Clone)]` container attribute
- Added `#[reflect(clone)]` field attribute
2025-03-11 06:02:59 +00:00
Zachary Harrold
ad016cb850
Improve bevy_reflect no_std support (#18060)
# Objective

- Fixes #18051

## Solution

- Switched function registry to use `bevy_platform_support::sync`
instead of `std::sync`
- Also documented that `debug_stack` (and transitively `debug`) require
`std`
- Also removed `std` from `wgpu-types` since that crate is now `no_std`
compatible

## Testing

- `cargo check -p bevy_reflect --no-default-features --features
critical-section,documentation,glam,glam/libm,smallvec,wgpu-types,functions
--target thumbv6m-none-eabi`

---

## Notes

With these changes, `bevy_reflect`'s feature support looks like this:

| Feature | `no_std` (Before) | `no_std` (After) | Notes |
| - | - | - | - |
| `default` |  |  | |
| `std` |  |  | |
| `documentation` | ✔️ | ✔️ | |
| `functions` |  | ✔️ | |
| `critical-section` | ✔️ | ✔️ | |
| `bevy` | ✔️* | ✔️* | Partial due to `smol_str` |
| `debug` |  |  | |
| `debug_stack` |  |  | |
| `petgraph` |  |  | |
| `glam` | ✔️* | ✔️* | Requires enabling `glam/libm` |
| `smallvec` | ✔️ | ✔️ | |
| `uuid` | ✔️* | ✔️* | Requires setting up `getrandom` backend |
| `wgpu-types ` |  | ✔️ | |
| `smol_str` | ✔️* | ✔️* | Partial due to `smol_str` not supporting
`portable-atomic` |
2025-02-27 06:16:10 +00:00
Zachary Harrold
76e9bf9c99
Automatically enable portable-atomic when required (#17570)
# Objective

- Contributes to #15460
- Reduce quantity and complexity of feature gates across Bevy

## Solution

- Used `target_has_atomic` configuration variable to automatically
detect impartial atomic support and automatically switch to
`portable-atomic` over the standard library on an as-required basis.

## Testing

- CI

## Notes

To explain the technique employed here, consider getting `Arc` either
from `alloc::sync` _or_ `portable-atomic-util`. First, we can inspect
the `alloc` crate to see that you only have access to `Arc` _if_
`target_has_atomic = "ptr"`. We add a target dependency for this
particular configuration _inverted_:

```toml
[target.'cfg(not(target_has_atomic = "ptr"))'.dependencies]
portable-atomic-util = { version = "0.2.4", default-features = false }
```

This ensures we only have the dependency when it is needed, and it is
entirely excluded from the dependency graph when it is not. Next, we
adjust our configuration flags to instead of checking for `feature =
"portable-atomic"` to instead check for `target_has_atomic = "ptr"`:

```rust
// `alloc` feature flag hidden for brevity

#[cfg(not(target_has_atomic = "ptr"))]
use portable_atomic_util as arc;

#[cfg(target_has_atomic = "ptr")]
use alloc::sync as arc;

pub use arc::{Arc, Weak};
```

The benefits of this technique are three-fold:

1. For platforms without full atomic support, the functionality is
enabled automatically.
2. For platforms with atomic support, the dependency is never included,
even if a feature was enabled using `--all-features` (for example)
3. The `portable-atomic` feature no longer needs to virally spread to
all user-facing crates, it's instead something handled within
`bevy_platform_support` (with some extras where other dependencies also
need their features enabled).
2025-02-24 20:52:46 +00:00
Zachary Harrold
5241e09671
Upgrade to Rust Edition 2024 (#17967)
# Objective

- Fixes #17960

## Solution

- Followed the [edition upgrade
guide](https://doc.rust-lang.org/edition-guide/editions/transitioning-an-existing-project-to-a-new-edition.html)

## Testing

- CI

---

## Summary of Changes

### Documentation Indentation

When using lists in documentation, proper indentation is now linted for.
This means subsequent lines within the same list item must start at the
same indentation level as the item.

```rust
/* Valid */
/// - Item 1
///   Run-on sentence.
/// - Item 2
struct Foo;

/* Invalid */
/// - Item 1
///     Run-on sentence.
/// - Item 2
struct Foo;
```

### Implicit `!` to `()` Conversion

`!` (the never return type, returned by `panic!`, etc.) no longer
implicitly converts to `()`. This is particularly painful for systems
with `todo!` or `panic!` statements, as they will no longer be functions
returning `()` (or `Result<()>`), making them invalid systems for
functions like `add_systems`. The ideal fix would be to accept functions
returning `!` (or rather, _not_ returning), but this is blocked on the
[stabilisation of the `!` type
itself](https://doc.rust-lang.org/std/primitive.never.html), which is
not done.

The "simple" fix would be to add an explicit `-> ()` to system
signatures (e.g., `|| { todo!() }` becomes `|| -> () { todo!() }`).
However, this is _also_ banned, as there is an existing lint which (IMO,
incorrectly) marks this as an unnecessary annotation.

So, the "fix" (read: workaround) is to put these kinds of `|| -> ! { ...
}` closuers into variables and give the variable an explicit type (e.g.,
`fn()`).

```rust
// Valid
let system: fn() = || todo!("Not implemented yet!");
app.add_systems(..., system);

// Invalid
app.add_systems(..., || todo!("Not implemented yet!"));
```

### Temporary Variable Lifetimes

The order in which temporary variables are dropped has changed. The
simple fix here is _usually_ to just assign temporaries to a named
variable before use.

### `gen` is a keyword

We can no longer use the name `gen` as it is reserved for a future
generator syntax. This involved replacing uses of the name `gen` with
`r#gen` (the raw-identifier syntax).

### Formatting has changed

Use statements have had the order of imports changed, causing a
substantial +/-3,000 diff when applied. For now, I have opted-out of
this change by amending `rustfmt.toml`

```toml
style_edition = "2021"
```

This preserves the original formatting for now, reducing the size of
this PR. It would be a simple followup to update this to 2024 and run
`cargo fmt`.

### New `use<>` Opt-Out Syntax

Lifetimes are now implicitly included in RPIT types. There was a handful
of instances where it needed to be added to satisfy the borrow checker,
but there may be more cases where it _should_ be added to avoid
breakages in user code.

### `MyUnitStruct { .. }` is an invalid pattern

Previously, you could match against unit structs (and unit enum
variants) with a `{ .. }` destructuring. This is no longer valid.

### Pretty much every use of `ref` and `mut` are gone

Pattern binding has changed to the point where these terms are largely
unused now. They still serve a purpose, but it is far more niche now.

### `iter::repeat(...).take(...)` is bad

New lint recommends using the more explicit `iter::repeat_n(..., ...)`
instead.

## Migration Guide

The lifetimes of functions using return-position impl-trait (RPIT) are
likely _more_ conservative than they had been previously. If you
encounter lifetime issues with such a function, please create an issue
to investigate the addition of `+ use<...>`.

## Notes

- Check the individual commits for a clearer breakdown for what
_actually_ changed.

---------

Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-02-24 03:54:47 +00:00
Alexandra
253cc6a77b
Add TypeRegistry::register_by_val (#17817)
# Objective

It is impossible to register a type with `TypeRegistry::register` if the
type is unnameable (in the current scope).

## Solution

Add `TypeRegistry::register_by_val` which mirrors std's `size_of_val`
and friends.

## Testing

There's a doc test (unrelated but there seem to be some pre-existing
broken doc links in `bevy_reflect`).
2025-02-15 19:07:01 +00:00
Rob Parrett
2760692f88
Update typos to 1.29.6 (#17850)
# Objective

Update typos, fix new typos.

1.29.6 was just released to fix an
[issue](https://github.com/crate-ci/typos/issues/1228) where January's
corrections were not included in the binaries for the last release.

Reminder: typos can be tossed in the monthly [non-critical corrections
issue](https://github.com/crate-ci/typos/issues/1221).

## Solution

I chose to allow `implementors`, because a good argument seems to be
being made [here](https://github.com/crate-ci/typos/issues/1226) and
there is now a PR to address that.

## Discussion

Should I exclude `bevy_mikktspace`?

At one point I think we had an informal policy of "don't mess with
mikktspace until https://github.com/bevyengine/bevy/pull/9050 is merged"
but it doesn't seem like that is likely to be merged any time soon.

I think these particular corrections in mikktspace are fine because
- The same typo mistake seems to have been fixed in that PR
- The entire file containing these corrections was deleted in that PR

## Typo of the Month

correspindong -> corresponding
2025-02-13 19:44:47 +00:00
raldone01
1b7db895b7
Harden proc macro path resolution and add integration tests. (#17330)
This pr uses the `extern crate self as` trick to make proc macros behave
the same way inside and outside bevy.

# Objective

- Removes noise introduced by `crate as` in the whole bevy repo.
- Fixes #17004.
- Hardens proc macro path resolution.

## TODO

- [x] `BevyManifest` needs cleanup.
- [x] Cleanup remaining `crate as`.
- [x] Add proper integration tests to the ci.

## Notes

- `cargo-manifest-proc-macros` is written by me and based/inspired by
the old `BevyManifest` implementation and
[`bkchr/proc-macro-crate`](https://github.com/bkchr/proc-macro-crate).
- What do you think about the new integration test machinery I added to
the `ci`?
  More and better integration tests can be added at a later stage.
The goal of these integration tests is to simulate an actual separate
crate that uses bevy. Ideally they would lightly touch all bevy crates.

## Testing

- Needs RA test
- Needs testing from other users
- Others need to run at least `cargo run -p ci integration-test` and
verify that they work.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-02-09 19:45:45 +00:00
aecsocket
f232674291
Remove unnecessary PartialReflect bound on DeserializeWithRegistry (#17560)
# Objective

The new `DeserializeWithRegistry` trait in 0.15 was designed to be used
with reflection, and so has a `trait DeserializeWithRegistry:
PartialReflect` bound. However, this bound is not actually necessary for
the trait to function properly. And this `PartialReflect` bound already
exists on:
```rs
impl<T: PartialReflect + for<'de> DeserializeWithRegistry<'de>> FromType<T>
    for ReflectDeserializeWithRegistry
```
So there is no point in constraining the trait itself with this bound as
well.

This lets me use `DeserializeWithRegistry` with non-`Reflect` types,
which I want to do to avoid making a bunch of `FooDeserializer` structs
and `impl DeserializeSeed` on them.

## Solution

Removes this unnecessary bound.

## Testing

Trivial change, does not break compilation or `bevy_reflect` tests.

## Migration Guide

`DeserializeWithRegistry` types are no longer guaranteed to be
`PartialReflect` as well. If you were relying on this type bound, you
should add it to your own bounds manually.
```diff
- impl<T: DeserializeWithRegistry> Foo for T { .. }
+ impl<T: DeserializeWithRegistry + PartialReflect> Foo for T { .. }
```
2025-01-29 17:36:39 +00:00
poopy
15f00278e7
Rename ArgList::push methods to with and add new push methods which take &mut self (#16567)
# Objective

The `ArgList::push` family of methods consume `self` and return a new
`ArgList` which means they can't be used with `&mut ArgList` references.

```rust
fn foo(args: &mut ArgList) {
    args.push_owned(47_i32); // doesn't work :(
}
```

It's typical for `push` methods on other existing types to take `&mut
self`.

## Solution

Renamed the existing push methods to `with_arg`, `with_ref` etc and
added new `push` methods which take `&mut self`.

## Migration Guide

Uses of the `ArgList::push` methods should be replaced with the `with`
counterpart.

<details>

| old | new |
| --- | --- |
| push_arg | with_arg |
| push_ref | with_ref |
| push_mut | with_mut |
| push_owned | with_owned | 
| push_boxed | with_boxed |

</details>
2025-01-28 05:06:50 +00:00
Zachary Harrold
9bc0ae33c3
Move hashbrown and foldhash out of bevy_utils (#17460)
# Objective

- Contributes to #16877

## Solution

- Moved `hashbrown`, `foldhash`, and related types out of `bevy_utils`
and into `bevy_platform_support`
- Refactored the above to match the layout of these types in `std`.
- Updated crates as required.

## Testing

- CI

---

## Migration Guide

- The following items were moved out of `bevy_utils` and into
`bevy_platform_support::hash`:
  - `FixedState`
  - `DefaultHasher`
  - `RandomState`
  - `FixedHasher`
  - `Hashed`
  - `PassHash`
  - `PassHasher`
  - `NoOpHash`
- The following items were moved out of `bevy_utils` and into
`bevy_platform_support::collections`:
  - `HashMap`
  - `HashSet`
- `bevy_utils::hashbrown` has been removed. Instead, import from
`bevy_platform_support::collections` _or_ take a dependency on
`hashbrown` directly.
- `bevy_utils::Entry` has been removed. Instead, import from
`bevy_platform_support::collections::hash_map` or
`bevy_platform_support::collections::hash_set` as appropriate.
- All of the above equally apply to `bevy::utils` and
`bevy::platform_support`.

## Notes

- I left `PreHashMap`, `PreHashMapExt`, and `TypeIdMap` in `bevy_utils`
as they might be candidates for micro-crating. They can always be moved
into `bevy_platform_support` at a later date if desired.
2025-01-23 16:46:08 +00:00
Zachary Harrold
04990fcd27
Move spin to bevy_platform_support out of other crates (#17470)
# Objective

- Contributes to #16877

## Solution

- Expanded `bevy_platform_support::sync` module to provide
API-compatible replacements for `std` items such as `RwLock`, `Mutex`,
and `OnceLock`.
- Removed `spin` from all crates except `bevy_platform_support`.

## Testing

- CI

---

## Notes

- The sync primitives, while verbose, entirely rely on `spin` for their
implementation requiring no `unsafe` and not changing the status-quo on
_how_ locks actually work within Bevy. This is just a refactoring to
consolidate the "hacks" and workarounds required to get a consistent
experience when either using `std::sync` or `spin`.
- I have opted to rely on `std::sync` for `std` compatible locks,
maintaining the status quo. However, now that we have these locks
factored out into the own module, it would be trivial to investigate
alternate locking backends, such as `parking_lot`.
- API for these locking types is entirely based on `std`. I have
implemented methods and types which aren't currently in use within Bevy
(e.g., `LazyLock` and `Once`) for the sake of completeness. As the
standard library is highly stable, I don't expect the Bevy and `std`
implementations to drift apart much if at all.

---------

Co-authored-by: BD103 <59022059+BD103@users.noreply.github.com>
Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-23 05:27:02 +00:00
Zachary Harrold
d921fdc376
Add no_std Support to bevy_time (#17491)
# Objective

- Contributes to #15460

## Solution

- Switched `tracing` for `log` for the atomically challenged platforms
- Setup feature flags as required
- Added to `compile-check-no-std` CI task
- Made `crossbeam-channel` optional depending on `std`.

## Testing

- CI

---

## Notes

- `crossbeam-channel` provides a MPMC channel type which isn't readily
replicable in `no_std`, and is only used for a `bevy_render`
integration. As such, I've feature-gated the `TimeReceiver` and
`TimeSender` types.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2025-01-22 20:02:43 +00:00
Alexander Krivács Schrøder
d56536a672
Add reflection to the remaining glam Vec types (#17493)
# Objective

Add reflection support to more `glam` `Vec` types, specifically

* I8Vec2
* I8Vec3
* I8Vec4
* U8Vec2
* U8Vec3
* U8Vec4
* I16Vec2
* I16Vec3
* I16Vec4
* U16Vec2
* U16Vec3
* U16Vec4

I needed to do this because I'm using various of these in my Bevy types,
and due to the orphan rules, I can't make these impls locally.

## Solution

Used `impl_reflect!` like for the existing types.

## Testing

This should not require additional testing, though I have verified that
reflection now works for these types in my own project.
2025-01-22 18:48:34 +00:00
Andreas Monitzer
000c362de0
Include ReflectFromReflect in all dynamic data types. (#17453)
# Objective

Fixes #17416

## Solution

I just included ReflectFromReflect in all macros and implementations. I
think this should be ok, at least it compiles properly and does fix the
errors in my test code.

## Testing

I generated a DynamicMap and tried to convert it into a concrete
`HashMap` as a `Box<dyn Reflect>`. Without my fix, it doesn't work,
because this line panics:

```rust
let rfr = ty.data::<ReflectFromReflect>().unwrap();
```

where `ty` is the `TypeRegistration` for the (matching) `HashMap`.

I don't know why `ReflectFromReflect` wasn't included everywhere, I
assume that it was an oversight and not an architecture decision I'm not
aware of.

# Migration Guide

The hasher in reflected `HashMap`s and `HashSet`s now have to implement
`Default`. This is the case for the ones provided by Bevy already, and
is generally a sensible thing to do.
2025-01-20 22:08:24 +00:00
Zachary Harrold
a64446b77e
Create bevy_platform_support Crate (#17250)
# Objective

- Contributes to #16877

## Solution

- Initial creation of `bevy_platform_support` crate.
- Moved `bevy_utils::Instant` into new `bevy_platform_support` crate.
- Moved `portable-atomic`, `portable-atomic-util`, and
`critical-section` into new `bevy_platform_support` crate.

## Testing

- CI

---

## Showcase

Instead of needing code like this to import an `Arc`:

```rust
#[cfg(feature = "portable-atomic")]
use portable_atomic_util::Arc;

#[cfg(not(feature = "portable-atomic"))]
use alloc::sync::Arc;
```

We can now use:

```rust
use bevy_platform_support::sync::Arc;
```

This applies to many other types, but the goal is overall the same:
allowing crates to use `std`-like types without the boilerplate of
conditional compilation and platform-dependencies.

## Migration Guide

- Replace imports of `bevy_utils::Instant` with
`bevy_platform_support::time::Instant`
- Replace imports of `bevy::utils::Instant` with
`bevy::platform_support::time::Instant`

## Notes

- `bevy_platform_support` hasn't been reserved on `crates.io`
- ~~`bevy_platform_support` is not re-exported from `bevy` at this time.
It may be worthwhile exporting this crate, but I am unsure of a
reasonable name to export it under (`platform_support` may be a bit
wordy for user-facing).~~
- I've included an implementation of `Instant` which is suitable for
`no_std` platforms that are not Wasm for the sake of eliminating feature
gates around its use. It may be a controversial inclusion, so I'm happy
to remove it if required.
- There are many other items (`spin`, `bevy_utils::Sync(Unsafe)Cell`,
etc.) which should be added to this crate. I have kept the initial scope
small to demonstrate utility without making this too unwieldy.

---------

Co-authored-by: TimJentzsch <TimJentzsch@users.noreply.github.com>
Co-authored-by: Chris Russell <8494645+chescock@users.noreply.github.com>
Co-authored-by: François Mockers <francois.mockers@vleue.com>
2025-01-20 20:45:30 +00:00
MichiRecRoom
26bb0b40d2
Move #![warn(clippy::allow_attributes, clippy::allow_attributes_without_reason)] to the workspace Cargo.toml (#17374)
# Objective
Fixes https://github.com/bevyengine/bevy/issues/17111

## Solution
Move `#![warn(clippy::allow_attributes,
clippy::allow_attributes_without_reason)]` to the workspace `Cargo.toml`

## Testing
Lots of CI testing, and local testing too.

---------

Co-authored-by: Benjamin Brienen <benjamin.brienen@outlook.com>
2025-01-15 01:14:58 +00:00
MichiRecRoom
447108b2a4
Downgrade clippy::allow_attributes and clippy::allow_attributes_without_reason to warn (#17320)
# Objective
I realized that setting these to `deny` may have been a little
aggressive - especially since we upgrade warnings to denies in CI.

## Solution
Downgrades these lints to `warn`, so that compiles can work locally. CI
will still treat these as denies.
2025-01-12 05:28:26 +00:00
Rob Parrett
b77e3ef33a
Fix a few typos (#17292)
# Objective

Stumbled upon a `from <-> form` transposition while reviewing a PR,
thought it was interesting, and went down a bit of a rabbit hole.

## Solution

Fix em
2025-01-10 22:48:30 +00:00
Nándor Szalma
7f74e3c2f9
Fix depth_bias and build errors on less capable platforms (#17079)
# Objective

- I'm compiling (parts of) bevy for an embedded platform with no 64bit
atomic and ctrlc handler support. Some compilation errors came up. This
PR contains the fixes for those.
- Fix depth_bias casting in PBR material (Fixes #14169)
  - Negative depth_bias values were casted to 0 before this PR
  - f32::INFINITY depth_bias value was casted to -1 before this PR

## Solutions

- Restrict 64bit atomic reflection to supported platforms
- Restrict ctrlc handler to supported platforms (linux, windows or macos
instead of "not wasm")
- The depth bias value (f32) is first casted to i32 then u64 in order to
preserve negative values

## Testing
- This version compiles on a platform with no 64bit atomic support, and
no ctrlc support
- CtrlC handler still works on Linux and Windows (I can't test on Macos)
- depth_bias:
```rust
println!("{}",f32::INFINITY as u64 as i32); // Prints: -1 (old implementation)
println!("{}",f32::INFINITY as i32 as u64 as i32); // Prints: 2147483647 (expected, new implementation)
```
Also ran a modified version of 3d_scene example with the following
results:

RED cube depth_bias: -1000.0
BLUE cube depth_bias: 0.0

![image](https://github.com/user-attachments/assets/d5a96759-dd3c-4a0a-97ff-821163873a0d)

RED cube depth_bias: -INF
BLUE cube depth_bias: 0.0

![image](https://github.com/user-attachments/assets/e4de22b4-0c31-4dea-8be1-12b700e440b9)

RED cube depth_bias: INF (case reported in #14169)
BLUE cube depth_bias: 0.0
(Im not completely sure whats going on with the shadows here, it seems
like depth_bias has some affect to those aswell, if this is
unintentional this issue was not introduced by this PR)

![image](https://github.com/user-attachments/assets/52d9348f-df27-468f-a001-2d3d3ff6b553)
2025-01-06 18:39:08 +00:00
Zachary Harrold
3c829d7f68
Remove everything except Instant from bevy_utils::time (#17158)
# Objective

- Contributes to #11478
- Contributes to #16877

## Solution

- Removed everything except `Instant` from `bevy_utils::time`

## Testing

- CI

---

## Migration Guide

If you relied on any of the following from `bevy_utils::time`:

- `Duration`
- `TryFromFloatSecsError`

Import these directly from `core::time` regardless of platform target
(WASM, mobile, etc.)

If you relied on any of the following from `bevy_utils::time`:

- `SystemTime`
- `SystemTimeError`

Instead import these directly from either `std::time` or `web_time` as
appropriate for your target platform.

## Notes

`Duration` and `TryFromFloatSecsError` are both re-exports from
`core::time` regardless of whether they are used from `web_time` or
`std::time`, so there is no value gained from re-exporting them from
`bevy_utils::time` as well. As for `SystemTime` and `SystemTimeError`,
no Bevy internal crates or examples rely on these types. Since Bevy
doesn't have a `Time<Wall>` resource for interacting with wall-time (and
likely shouldn't need one), I think removing these from `bevy_utils`
entirely and waiting for a use-case to justify inclusion is a reasonable
path forward.
2025-01-05 20:36:08 +00:00
Benjamin Brienen
7112d5594e
Remove all deprecated code (#16338)
# Objective

Release cycle things

## Solution

Delete items deprecated in 0.15 and migrate bevy itself.

## Testing

CI
2025-01-05 20:33:39 +00:00
MichiRecRoom
5f5876b1c9
Change bevy_reflect::RegisterForReflection::__register() to expect unused variables, rather than putting underscores on the parameter names (#17171)
# Objective
While checking over https://github.com/bevyengine/bevy/pull/17160, it
occurred to me that rust-analyzer will copy the method signature
exactly, when using tab completion trait methods. This includes provided
trait methods that use underscores to silence the `unused_variables`
lint. This probably isn't good for users, seeing as how they'll have to
remove the underscore if they want to use the parameters.

(I mean, they technically don't have to remove the underscore... but
usually you don't keep a leading underscore on parameters you're using.)

## Solution
Changes `bevy_reflect::RegisterForReflection::__register()` to
`#[expect(unused_variables)]`, and removes the underscores from its
parameter names.

## Testing
N/A
2025-01-05 20:27:20 +00:00
Sean Kim
f90a41ff72
Update GetPath unit test and documentation for empty path usecase (#17150)
# Objective

- `GetPath` `path` related methods allow an empty string as the
parameter, but this is not included as a test or in documentation. This
PR adds both.
- Fixes #13459

## Solution

- Updates the `bevy_reflect` `GetPath` documentation and unit tests

## Testing

- `cargo run -p ci`
2025-01-05 02:45:26 +00:00
MichiRecRoom
120b733ab5
bevy_reflect: Apply #[deny(clippy::allow_attributes, clippy::allow_attributes_without_reason)] (#17092)
# Objective
We want to deny the following lints:
* `clippy::allow_attributes` - Because there's no reason to
`#[allow(...)]` an attribute if it wouldn't lint against anything; you
should always use `#[expect(...)]`
* `clippy::allow_attributes_without_reason` - Because documenting the
reason for allowing/expecting a lint is always good

## Solution
Set the `clippy::allow_attributes` and
`clippy::allow_attributes_without_reason` lints to `deny`, and bring
`bevy_reflect` in line with the new restrictions.

No code changes have been made - except if a lint that was previously
`allow(...)`'d could be removed via small code changes. For example,
`unused_variables` can be handled by adding a `_` to the beginning of a
field's name.

## Testing
I ran `cargo clippy`, and received no errors.
2025-01-03 22:22:34 +00:00
Rob Parrett
651b22f31f
Update typos (#17126)
# Objective

Use the latest version of `typos` and fix the typos that it now detects

# Additional Info

By the way, `typos` has a "low priority typo suggestions issue" where we
can throw typos we find that `typos` doesn't catch.

(This link may go stale) https://github.com/crate-ci/typos/issues/1200
2025-01-03 17:44:26 +00:00