bevyengine / bevyengine/bevy

Confusing trait bounds on `MaterialPlugin`

Open
#17,165 2 comments 0 reactions 0 assignees View on GitHub
A-Rendering C-Docs D-Straightforward S-Needs-Design
Dominant language
Rust
Stars
48.2k
Forks
4.8k
Avg merge
3d 22h
Merged PRs (30d)
161

Description

```rust
use bevy::{prelude::*, render::render_resource::AsBindGroup};

//#[derive(Clone, Copy, PartialEq, Eq, Hash)]
struct TestMaterialKey {
data: u8,
}
impl From<&TestMaterial> for TestMaterialKey {
fn from(value: &TestMaterial) -> Self {
Self {
data: value.data
}
}
}

#[derive(Clone, TypePath, AsBindGroup, Asset)]
#[bind_group_data(TestMaterialKey)]
struct TestMaterial {
data: u8
}
impl Material for TestMaterial { }

fn main() {
App::new().add_plugins(MaterialPlugin::::default()).run();
}
```
Does not compile, with the error:
```rust
error[E0277]: the trait bound `bevy::prelude::MaterialPlugin: Plugins<_>` is not satisfied
--> src/main.rs:23:28
|
23 | App::new().add_plugins(MaterialPlugin::::default()).run();
| ----------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `bevy::bevy_app::plugin::sealed::Plugins<_>` is not implemented for `bevy::prelude::MaterialPlugin`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `bevy::bevy_app::plugin::sealed::Plugins`:
`()` implements `bevy::bevy_app::plugin::sealed::Plugins<(bevy::bevy_app::plugin::sealed::PluginsTupleMarker,)>`
`(S,)` implements `bevy::bevy_app::plugin::sealed::Plugins<(bevy::bevy_app::plugin::sealed::PluginsTupleMarker, P)>`
`(S0, S1)` implements `bevy::bevy_app::plugin::sealed::Plugins<(bevy::bevy_app::plugin::sealed::PluginsTupleMarker, P0, P1)>`
`(S0, S1, S2)` implements `bevy::bevy_app::plugin::sealed::Plugins<(bevy::bevy_app::plugin::sealed::PluginsTupleMarker, P0, P1, P2)>`
`(S0, S1, S2, S3)` implements `bevy::bevy_app::plugin::sealed::Plugins<(bevy::bevy_app::plugin::sealed::PluginsTupleMarker, P0, P1, P2, P3)>`
`(S0, S1, S2, S3, S4)` implements `bevy::bevy_app::plugin::sealed::Plugins<(bevy::bevy_app::plugin::sealed::PluginsTupleMarker, P0, P1, P2, P3, P4)>`
`(S0, S1, S2, S3, S4, S5)` implements `bevy::bevy_app::plugin::sealed::Plugins<(bevy::bevy_app::plugin::sealed::PluginsTupleMarker, P0, P1, P2, P3, P4, P5)>`
`(S0, S1, S2, S3, S4, S5, S6)` implements `bevy::bevy_app::plugin::sealed::Plugins<(bevy::bevy_app::plugin::sealed::PluginsTupleMarker, P0, P1, P2, P3, P4, P5, P6)>`
and 8 others
= note: required for `bevy::prelude::MaterialPlugin` to implement `Plugins<_>`
note: required by a bound in `bevy::prelude::App::add_plugins`
--> /home/jacobs/.cargo/registry/src/index.crates.io-6f17d22bba15001f/bevy_app-0.15.1/src/app.rs:548:52
|
548 | pub fn add_plugins(&mut self, plugins: impl Plugins) -> &mut Self {
| ^^^^^^^^^^ required by this bound in `App::add_plugins`
```
Uncommenting `#[derive(Clone, Copy, PartialEq, Eq, Hash)]` fixes the error.
The reason this does not work, is that `impl Plugin for MaterialPlugin` requires `::Data: PartialEq + Eq + Hash + Clone` however this is a pretty sneaky trait bound that is very easy to look over. I think that it should be a trait bound on `MaterialPlugin` too so that when a user attempts to do this they get a much more useful error. Failing that, I think more attention should be drawn to this in the docs because currently it's very easy to assume that any `MaterialPlugin` you are allowed to construct would implement `Plugin`. It's in the name after all.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.