bevy/crates
Gino Valente 56686a8962
bevy_derive: Add #[deref] attribute (#8552)
# Objective

Bevy code tends to make heavy use of the [newtype](
https://doc.rust-lang.org/rust-by-example/generics/new_types.html)
pattern, which is why we have a dedicated derive for
[`Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and
[`DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html).
This derive works for any struct with a single field:

```rust
#[derive(Component, Deref, DerefMut)]
struct MyNewtype(usize);
```

One reason for the single-field limitation is to prevent confusion and
footguns related that would arise from allowing multi-field structs:

<table align="center">
<tr>
<th colspan="2">
Similar structs, different derefs
</th>
</tr>
<tr>
<td>

```rust
#[derive(Deref, DerefMut)]
struct MyStruct {
  foo: usize, // <- Derefs usize
  bar: String,
}
```

</td>
<td>

```rust
#[derive(Deref, DerefMut)]
struct MyStruct {
  bar: String, // <- Derefs String
  foo: usize,
}
```

</td>
</tr>
<tr>
<th colspan="2">
Why `.1`?
</th>
</tr>
<tr>
<td colspan="2">

```rust
#[derive(Deref, DerefMut)]
struct MyStruct(Vec<usize>, Vec<f32>);

let mut foo = MyStruct(vec![123], vec![1.23]);

// Why can we skip the `.0` here?
foo.push(456);
// But not here?
foo.1.push(4.56);
```

</td>
</tr>
</table>

However, there are certainly cases where it's useful to allow for
structs with multiple fields. Such as for structs with one "real" field
and one `PhantomData` to allow for generics:

```rust
#[derive(Deref, DerefMut)]
struct MyStruct<T>(
  // We want use this field for the `Deref`/`DerefMut` impls
  String,
  // But we need this field so that we can make this struct generic
  PhantomData<T>
);

// ERROR: Deref can only be derived for structs with a single field
// ERROR: DerefMut can only be derived for structs with a single field
```

Additionally, the possible confusion and footguns are mainly an issue
for newer Rust/Bevy users. Those familiar with `Deref` and `DerefMut`
understand what adding the derive really means and can anticipate its
behavior.

## Solution

Allow users to opt into multi-field `Deref`/`DerefMut` derives using a
`#[deref]` attribute:

```rust
#[derive(Deref, DerefMut)]
struct MyStruct<T>(
  // Use this field for the `Deref`/`DerefMut` impls
  #[deref] String,
  // We can freely include any other field without a compile error
  PhantomData<T>
);
```

This prevents the footgun pointed out in the first issue described in
the previous section, but it still leaves the possible confusion
surrounding `.0`-vs-`.#`. However, the idea is that by making this
behavior explicit with an attribute, users will be more aware of it and
can adapt appropriately.

---

## Changelog

- Added `#[deref]` attribute to `Deref` and `DerefMut` derives
2023-05-16 18:29:09 +00:00
..
bevy_a11y Suppress the clippy::type_complexity lint (#8313) 2023-04-06 21:27:36 +00:00
bevy_animation Fixed several missing links in docs. (#8117) 2023-04-23 17:28:36 +00:00
bevy_app Merge ScheduleRunnerSettings into ScheduleRunnerPlugin (#8585) 2023-05-10 16:46:21 +00:00
bevy_asset Delay asset hot reloading (#8503) 2023-05-16 01:26:11 +00:00
bevy_audio Ability to set a Global Volume (#7706) 2023-04-10 14:08:43 +00:00
bevy_core Add Reflect and FromReflect for AssetPath (#8531) 2023-05-08 19:19:19 +00:00
bevy_core_pipeline Add ViewNode to simplify render node management (#8118) 2023-05-08 19:42:23 +00:00
bevy_derive bevy_derive: Add #[deref] attribute (#8552) 2023-05-16 18:29:09 +00:00
bevy_diagnostic Suppress the clippy::type_complexity lint (#8313) 2023-04-06 21:27:36 +00:00
bevy_dylib Suppress the clippy::type_complexity lint (#8313) 2023-04-06 21:27:36 +00:00
bevy_dynamic_plugin Suppress the clippy::type_complexity lint (#8313) 2023-04-06 21:27:36 +00:00
bevy_ecs Fix a change detection test (#8605) 2023-05-16 01:41:24 +00:00
bevy_ecs_compile_fail_tests Fix 1.69 CI clippy lints (#8450) 2023-04-20 16:51:21 +00:00
bevy_encase_derive update syn, encase, glam and hexasphere (#8573) 2023-05-16 01:24:17 +00:00
bevy_gilrs Add gamepad rumble support to bevy_input (#8398) 2023-04-24 15:28:53 +00:00
bevy_gizmos Webgpu support (#8336) 2023-05-04 22:07:57 +00:00
bevy_gltf Add support for custom glTF vertex attributes. (#5370) 2023-04-24 14:20:13 +00:00
bevy_hierarchy Expose sorting methods in Children (#8522) 2023-05-01 15:57:25 +00:00
bevy_input Fix typos in gamepad AxisSettings (#8542) 2023-05-04 23:23:45 +00:00
bevy_internal Take example screenshots in CI (#8488) 2023-05-01 18:00:01 +00:00
bevy_log add a feature for memory tracing with tracy (#8272) 2023-04-17 16:04:46 +00:00
bevy_macro_utils update syn, encase, glam and hexasphere (#8573) 2023-05-16 01:24:17 +00:00
bevy_macros_compile_fail_tests bevy_derive: Add #[deref] attribute (#8552) 2023-05-16 18:29:09 +00:00
bevy_math update syn, encase, glam and hexasphere (#8573) 2023-05-16 01:24:17 +00:00
bevy_mikktspace update syn, encase, glam and hexasphere (#8573) 2023-05-16 01:24:17 +00:00
bevy_pbr Webgpu support (#8336) 2023-05-04 22:07:57 +00:00
bevy_ptr Fixed several missing links in docs. (#8117) 2023-04-23 17:28:36 +00:00
bevy_reflect update syn, encase, glam and hexasphere (#8573) 2023-05-16 01:24:17 +00:00
bevy_reflect_compile_fail_tests Fix 1.69 CI clippy lints (#8450) 2023-04-20 16:51:21 +00:00
bevy_render update syn, encase, glam and hexasphere (#8573) 2023-05-16 01:24:17 +00:00
bevy_scene Rename map_entities and map_specific_entities (#7570) 2023-05-01 21:40:19 +00:00
bevy_sprite Webgpu support (#8336) 2023-05-04 22:07:57 +00:00
bevy_tasks Fixed several missing links in docs. (#8117) 2023-04-23 17:28:36 +00:00
bevy_text Fix panic when using debug_asset_server (#8485) 2023-04-25 10:11:11 +00:00
bevy_time Take example screenshots in CI (#8488) 2023-05-01 18:00:01 +00:00
bevy_transform Add a bounding box gizmo (#8468) 2023-04-24 15:23:06 +00:00
bevy_ui Flatten UI Style properties that use Size + remove Size (#8548) 2023-05-16 01:36:32 +00:00
bevy_utils update syn, encase, glam and hexasphere (#8573) 2023-05-16 01:24:17 +00:00
bevy_window Make scene handling of entity references robust (#7335) 2023-05-01 15:49:27 +00:00
bevy_winit Webgpu support (#8336) 2023-05-04 22:07:57 +00:00