Skip to content

Commit 95cb9e3

Browse files
committed
Fixed bounds for normal FromReflect derive
1 parent 56d11a2 commit 95cb9e3

File tree

7 files changed

+48
-11
lines changed

7 files changed

+48
-11
lines changed

crates/bevy_reflect/bevy_reflect_derive/src/container_attributes.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ pub(crate) struct ReflectTraits {
170170
}
171171

172172
impl ReflectTraits {
173-
pub fn from_metas(metas: Punctuated<Meta, Comma>) -> Result<Self, syn::Error> {
173+
pub fn from_metas(
174+
metas: Punctuated<Meta, Comma>,
175+
is_from_reflect_derive: bool,
176+
) -> Result<Self, syn::Error> {
174177
let mut traits = ReflectTraits::default();
175178
for meta in &metas {
176179
match meta {
@@ -245,7 +248,14 @@ impl ReflectTraits {
245248
syn::Expr::Lit(syn::ExprLit {
246249
lit: syn::Lit::Bool(lit),
247250
..
248-
}) => Some(lit.clone()),
251+
}) => {
252+
// Overrride `lit` if this is a `FromReflect` derive.
253+
// This typically means a user is opting out of the default implementation
254+
// from the `Reflect` derive and using the `FromReflect` derive directly instead.
255+
is_from_reflect_derive
256+
.then(|| LitBool::new(true, Span::call_site()))
257+
.or_else(|| Some(lit.clone()))
258+
}
249259
_ => {
250260
return Err(syn::Error::new(
251261
pair.value.span(),
@@ -366,7 +376,7 @@ impl ReflectTraits {
366376

367377
impl Parse for ReflectTraits {
368378
fn parse(input: ParseStream) -> syn::Result<Self> {
369-
ReflectTraits::from_metas(Punctuated::<Meta, Comma>::parse_terminated(input)?)
379+
ReflectTraits::from_metas(Punctuated::<Meta, Comma>::parse_terminated(input)?, false)
370380
}
371381
}
372382

crates/bevy_reflect/bevy_reflect_derive/src/derive_data.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,10 @@ enum ReflectMode {
134134
}
135135

136136
impl<'a> ReflectDerive<'a> {
137-
pub fn from_input(input: &'a DeriveInput) -> Result<Self, syn::Error> {
137+
pub fn from_input(
138+
input: &'a DeriveInput,
139+
is_from_reflect_derive: bool,
140+
) -> Result<Self, syn::Error> {
138141
let mut traits = ReflectTraits::default();
139142
// Should indicate whether `#[reflect_value]` was used.
140143
let mut reflect_mode = None;
@@ -159,6 +162,7 @@ impl<'a> ReflectDerive<'a> {
159162
reflect_mode = Some(ReflectMode::Normal);
160163
let new_traits = ReflectTraits::from_metas(
161164
meta_list.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)?,
165+
is_from_reflect_derive,
162166
)?;
163167
traits.merge(new_traits)?;
164168
}
@@ -173,6 +177,7 @@ impl<'a> ReflectDerive<'a> {
173177
reflect_mode = Some(ReflectMode::Value);
174178
let new_traits = ReflectTraits::from_metas(
175179
meta_list.parse_args_with(Punctuated::<Meta, Comma>::parse_terminated)?,
180+
is_from_reflect_derive,
176181
)?;
177182
traits.merge(new_traits)?;
178183
}

crates/bevy_reflect/bevy_reflect_derive/src/lib.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ pub(crate) static TYPE_NAME_ATTRIBUTE_NAME: &str = "type_name";
156156
pub fn derive_reflect(input: TokenStream) -> TokenStream {
157157
let ast = parse_macro_input!(input as DeriveInput);
158158

159-
let derive_data = match ReflectDerive::from_input(&ast) {
159+
let derive_data = match ReflectDerive::from_input(&ast, false) {
160160
Ok(data) => data,
161161
Err(err) => return err.into_compile_error().into(),
162162
};
@@ -232,7 +232,7 @@ pub fn derive_reflect(input: TokenStream) -> TokenStream {
232232
pub fn derive_from_reflect(input: TokenStream) -> TokenStream {
233233
let ast = parse_macro_input!(input as DeriveInput);
234234

235-
let derive_data = match ReflectDerive::from_input(&ast) {
235+
let derive_data = match ReflectDerive::from_input(&ast, true) {
236236
Ok(data) => data,
237237
Err(err) => return err.into_compile_error().into(),
238238
};
@@ -266,7 +266,7 @@ pub fn derive_from_reflect(input: TokenStream) -> TokenStream {
266266
#[proc_macro_derive(TypePath, attributes(type_path, type_name))]
267267
pub fn derive_type_path(input: TokenStream) -> TokenStream {
268268
let ast = parse_macro_input!(input as DeriveInput);
269-
let derive_data = match ReflectDerive::from_input(&ast) {
269+
let derive_data = match ReflectDerive::from_input(&ast, false) {
270270
Ok(data) => data,
271271
Err(err) => return err.into_compile_error().into(),
272272
};
@@ -434,7 +434,7 @@ pub fn impl_reflect_value(input: TokenStream) -> TokenStream {
434434
#[proc_macro]
435435
pub fn impl_reflect_struct(input: TokenStream) -> TokenStream {
436436
let ast = parse_macro_input!(input as DeriveInput);
437-
let derive_data = match ReflectDerive::from_input(&ast) {
437+
let derive_data = match ReflectDerive::from_input(&ast, false) {
438438
Ok(data) => data,
439439
Err(err) => return err.into_compile_error().into(),
440440
};

crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/from_reflect.fail.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use bevy_reflect::Reflect;
1+
use bevy_reflect::{FromReflect, Reflect};
22

33
// Reason: Cannot have conflicting `from_reflect` attributes
44
#[derive(Reflect)]
@@ -16,4 +16,10 @@ struct Bar {
1616
value: String,
1717
}
1818

19+
// Reason: Conflicting `FromReflect` implementations
20+
#[derive(Reflect, FromReflect)]
21+
struct Baz {
22+
value: String,
23+
}
24+
1925
fn main() {}

crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/from_reflect.fail.stderr

+10
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,13 @@ error: `from_reflect` already set to true
99
|
1010
14 | #[reflect(from_reflect = false)]
1111
| ^^^^^
12+
13+
error[E0119]: conflicting implementations of trait `FromReflect` for type `Baz`
14+
--> tests/reflect_derive/from_reflect.fail.rs:20:19
15+
|
16+
20 | #[derive(Reflect, FromReflect)]
17+
| ------- ^^^^^^^^^^^ conflicting implementation for `Baz`
18+
| |
19+
| first implementation here
20+
|
21+
= note: this error originates in the derive macro `FromReflect` (in Nightly builds, run with -Z macro-backtrace for more info)

crates/bevy_reflect_compile_fail_tests/tests/reflect_derive/from_reflect.pass.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use bevy_reflect::Reflect;
1+
use bevy_reflect::{FromReflect, Reflect};
22

33
#[derive(Reflect)]
44
#[reflect(from_reflect = false)]
@@ -14,4 +14,10 @@ struct Bar {
1414
value: String,
1515
}
1616

17+
#[derive(Reflect, FromReflect)]
18+
#[reflect(from_reflect = false)]
19+
struct Baz {
20+
value: String,
21+
}
22+
1723
fn main() {}

examples/reflection/reflection.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ fn main() {
3333
/// To do this, you can either define a `#[reflect(default = "...")]` attribute on the ignored field, or
3434
/// opt-out of `FromReflect`'s auto-derive using the `#[reflect(from_reflect = false)]` attribute.
3535
#[derive(Reflect)]
36-
#[from_reflect(auto_derive = false)]
36+
#[reflect(from_reflect = false)]
3737
pub struct Foo {
3838
a: usize,
3939
nested: Bar,

0 commit comments

Comments
 (0)