
# Objective
- Followup to #7184.
- ~Deprecate `TypeUuid` and remove its internal references.~ No longer
part of this PR.
- Use `TypePath` for the type registry, and (de)serialisation instead of
`std::any::type_name`.
- Allow accessing type path information behind proxies.
## Solution
- Introduce methods on `TypeInfo` and friends for dynamically querying
type path. These methods supersede the old `type_name` methods.
- Remove `Reflect::type_name` in favor of `DynamicTypePath::type_path`
and `TypeInfo::type_path_table`.
- Switch all uses of `std::any::type_name` in reflection, non-debugging
contexts to use `TypePath`.
---
## Changelog
- Added `TypePathTable` for dynamically accessing methods on `TypePath`
through `TypeInfo` and the type registry.
- Removed `type_name` from all `TypeInfo`-like structs.
- Added `type_path` and `type_path_table` methods to all `TypeInfo`-like
structs.
- Removed `Reflect::type_name` in favor of
`DynamicTypePath::reflect_type_path` and `TypeInfo::type_path`.
- Changed the signature of all `DynamicTypePath` methods to return
strings with a static lifetime.
## Migration Guide
- Rely on `TypePath` instead of `std::any::type_name` for all stability
guarantees and for use in all reflection contexts, this is used through
with one of the following APIs:
- `TypePath::type_path` if you have a concrete type and not a value.
- `DynamicTypePath::reflect_type_path` if you have an `dyn Reflect`
value without a concrete type.
- `TypeInfo::type_path` for use through the registry or if you want to
work with the represented type of a `DynamicFoo`.
- Remove `type_name` from manual `Reflect` implementations.
- Use `type_path` and `type_path_table` in place of `type_name` on
`TypeInfo`-like structs.
- Use `get_with_type_path(_mut)` over `get_with_type_name(_mut)`.
## Note to reviewers
I think if anything we were a little overzealous in merging #7184 and we
should take that extra care here.
In my mind, this is the "point of no return" for `TypePath` and while I
think we all agree on the design, we should carefully consider if the
finer details and current implementations are actually how we want them
moving forward.
For example [this incorrect `TypePath` implementation for
`String`](3fea3c6c0b/crates/bevy_reflect/src/impls/std.rs (L90)
)
(note that `String` is in the default Rust prelude) snuck in completely
under the radar.
636 lines
19 KiB
Rust
636 lines
19 KiB
Rust
mod dynamic_enum;
|
|
mod enum_trait;
|
|
mod helpers;
|
|
mod variants;
|
|
|
|
pub use dynamic_enum::*;
|
|
pub use enum_trait::*;
|
|
pub use helpers::*;
|
|
pub use variants::*;
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate as bevy_reflect;
|
|
use crate::*;
|
|
|
|
#[derive(Reflect, Debug, PartialEq)]
|
|
enum MyEnum {
|
|
A,
|
|
B(usize, i32),
|
|
C { foo: f32, bar: bool },
|
|
}
|
|
|
|
#[test]
|
|
fn should_get_enum_type_info() {
|
|
let info = MyEnum::type_info();
|
|
if let TypeInfo::Enum(info) = info {
|
|
assert!(info.is::<MyEnum>(), "expected type to be `MyEnum`");
|
|
assert_eq!(MyEnum::type_path(), info.type_path());
|
|
assert_eq!(MyEnum::type_path(), info.type_path_table().path());
|
|
assert_eq!(MyEnum::type_ident(), info.type_path_table().ident());
|
|
assert_eq!(MyEnum::module_path(), info.type_path_table().module_path());
|
|
assert_eq!(MyEnum::crate_name(), info.type_path_table().crate_name());
|
|
assert_eq!(
|
|
MyEnum::short_type_path(),
|
|
info.type_path_table().short_path()
|
|
);
|
|
|
|
// === MyEnum::A === //
|
|
assert_eq!("A", info.variant_at(0).unwrap().name());
|
|
assert_eq!("A", info.variant("A").unwrap().name());
|
|
if let VariantInfo::Unit(variant) = info.variant("A").unwrap() {
|
|
assert_eq!("A", variant.name());
|
|
} else {
|
|
panic!("Expected `VariantInfo::Unit`");
|
|
}
|
|
|
|
// === MyEnum::B === //
|
|
assert_eq!("B", info.variant_at(1).unwrap().name());
|
|
assert_eq!("B", info.variant("B").unwrap().name());
|
|
if let VariantInfo::Tuple(variant) = info.variant("B").unwrap() {
|
|
assert!(variant.field_at(0).unwrap().is::<usize>());
|
|
assert!(variant.field_at(1).unwrap().is::<i32>());
|
|
} else {
|
|
panic!("Expected `VariantInfo::Tuple`");
|
|
}
|
|
|
|
// === MyEnum::C === //
|
|
assert_eq!("C", info.variant_at(2).unwrap().name());
|
|
assert_eq!("C", info.variant("C").unwrap().name());
|
|
if let VariantInfo::Struct(variant) = info.variant("C").unwrap() {
|
|
assert!(variant.field_at(0).unwrap().is::<f32>());
|
|
assert!(variant.field("foo").unwrap().is::<f32>());
|
|
} else {
|
|
panic!("Expected `VariantInfo::Struct`");
|
|
}
|
|
} else {
|
|
panic!("Expected `TypeInfo::Enum`");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn dynamic_enum_should_set_variant_fields() {
|
|
// === Unit === //
|
|
let mut value = MyEnum::A;
|
|
let dyn_enum = DynamicEnum::from(MyEnum::A);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(MyEnum::A, value);
|
|
|
|
// === Tuple === //
|
|
let mut value = MyEnum::B(0, 0);
|
|
let dyn_enum = DynamicEnum::from(MyEnum::B(123, 321));
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(MyEnum::B(123, 321), value);
|
|
|
|
// === Struct === //
|
|
let mut value = MyEnum::C {
|
|
foo: 0.0,
|
|
bar: false,
|
|
};
|
|
let dyn_enum = DynamicEnum::from(MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true,
|
|
});
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(
|
|
MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true,
|
|
},
|
|
value
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn partial_dynamic_enum_should_set_variant_fields() {
|
|
// === Tuple === //
|
|
let mut value = MyEnum::B(0, 0);
|
|
|
|
let mut data = DynamicTuple::default();
|
|
data.insert(123usize);
|
|
|
|
let mut dyn_enum = DynamicEnum::default();
|
|
dyn_enum.set_variant("B", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(MyEnum::B(123, 0), value);
|
|
|
|
// === Struct === //
|
|
let mut value = MyEnum::C {
|
|
foo: 1.23,
|
|
bar: false,
|
|
};
|
|
|
|
let mut data = DynamicStruct::default();
|
|
data.insert("bar", true);
|
|
|
|
let mut dyn_enum = DynamicEnum::default();
|
|
dyn_enum.set_variant("C", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(
|
|
MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true,
|
|
},
|
|
value
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn dynamic_enum_should_apply_dynamic_enum() {
|
|
let mut a = DynamicEnum::from(MyEnum::B(123, 321));
|
|
let b = DynamicEnum::from(MyEnum::B(123, 321));
|
|
|
|
// Sanity check that equality check works
|
|
assert!(
|
|
a.reflect_partial_eq(&b).unwrap_or_default(),
|
|
"dynamic enums should be equal"
|
|
);
|
|
|
|
a.set_variant("A", ());
|
|
assert!(
|
|
!a.reflect_partial_eq(&b).unwrap_or_default(),
|
|
"dynamic enums should not be equal"
|
|
);
|
|
|
|
a.apply(&b);
|
|
assert!(a.reflect_partial_eq(&b).unwrap_or_default());
|
|
}
|
|
|
|
#[test]
|
|
fn dynamic_enum_should_change_variant() {
|
|
let mut value = MyEnum::A;
|
|
|
|
// === MyEnum::A -> MyEnum::B === //
|
|
let mut dyn_enum = DynamicEnum::from(MyEnum::B(123, 321));
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(MyEnum::B(123, 321), value);
|
|
|
|
// === MyEnum::B -> MyEnum::C === //
|
|
let mut data = DynamicStruct::default();
|
|
data.insert("foo", 1.23_f32);
|
|
data.insert("bar", true);
|
|
dyn_enum.set_variant("C", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(
|
|
MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true
|
|
},
|
|
value
|
|
);
|
|
|
|
// === MyEnum::C -> MyEnum::B === //
|
|
let mut data = DynamicTuple::default();
|
|
data.insert(123_usize);
|
|
data.insert(321_i32);
|
|
dyn_enum.set_variant("B", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(MyEnum::B(123, 321), value);
|
|
|
|
// === MyEnum::B -> MyEnum::A === //
|
|
dyn_enum.set_variant("A", ());
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(MyEnum::A, value);
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_iterate_fields() {
|
|
// === Unit === //
|
|
let value: &dyn Enum = &MyEnum::A;
|
|
assert_eq!(0, value.field_len());
|
|
let mut iter = value.iter_fields();
|
|
assert!(iter.next().is_none());
|
|
|
|
// === Tuple === //
|
|
let value: &dyn Enum = &MyEnum::B(123, 321);
|
|
assert_eq!(2, value.field_len());
|
|
let mut iter = value.iter_fields();
|
|
assert!(iter
|
|
.next()
|
|
.and_then(|field| field.value().reflect_partial_eq(&123_usize))
|
|
.unwrap_or_default());
|
|
assert!(iter
|
|
.next()
|
|
.and_then(|field| field.value().reflect_partial_eq(&321_i32))
|
|
.unwrap_or_default());
|
|
|
|
// === Struct === //
|
|
let value: &dyn Enum = &MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true,
|
|
};
|
|
assert_eq!(2, value.field_len());
|
|
let mut iter = value.iter_fields();
|
|
assert!(iter
|
|
.next()
|
|
.and_then(|field| field
|
|
.value()
|
|
.reflect_partial_eq(&1.23_f32)
|
|
.and(field.name().map(|name| name == "foo")))
|
|
.unwrap_or_default());
|
|
assert!(iter
|
|
.next()
|
|
.and_then(|field| field
|
|
.value()
|
|
.reflect_partial_eq(&true)
|
|
.and(field.name().map(|name| name == "bar")))
|
|
.unwrap_or_default());
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_return_correct_variant_type() {
|
|
// === Unit === //
|
|
let value = MyEnum::A;
|
|
assert_eq!(VariantType::Unit, value.variant_type());
|
|
|
|
// === Tuple === //
|
|
let value = MyEnum::B(0, 0);
|
|
assert_eq!(VariantType::Tuple, value.variant_type());
|
|
|
|
// === Struct === //
|
|
let value = MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true,
|
|
};
|
|
assert_eq!(VariantType::Struct, value.variant_type());
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_return_correct_variant_path() {
|
|
// === Unit === //
|
|
let value = MyEnum::A;
|
|
assert_eq!(
|
|
"bevy_reflect::enums::tests::MyEnum::A",
|
|
value.variant_path()
|
|
);
|
|
|
|
// === Tuple === //
|
|
let value = MyEnum::B(0, 0);
|
|
assert_eq!(
|
|
"bevy_reflect::enums::tests::MyEnum::B",
|
|
value.variant_path()
|
|
);
|
|
|
|
// === Struct === //
|
|
let value = MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true,
|
|
};
|
|
assert_eq!(
|
|
"bevy_reflect::enums::tests::MyEnum::C",
|
|
value.variant_path()
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic(expected = "`bevy_reflect::DynamicTuple` is not an enum")]
|
|
fn applying_non_enum_should_panic() {
|
|
let mut value = MyEnum::B(0, 0);
|
|
let mut dyn_tuple = DynamicTuple::default();
|
|
dyn_tuple.insert((123_usize, 321_i32));
|
|
value.apply(&dyn_tuple);
|
|
}
|
|
|
|
#[test]
|
|
fn should_skip_ignored_fields() {
|
|
#[derive(Reflect, Debug, PartialEq)]
|
|
enum TestEnum {
|
|
A,
|
|
B,
|
|
C {
|
|
#[reflect(ignore)]
|
|
foo: f32,
|
|
bar: bool,
|
|
},
|
|
}
|
|
|
|
if let TypeInfo::Enum(info) = TestEnum::type_info() {
|
|
assert_eq!(3, info.variant_len());
|
|
if let VariantInfo::Struct(variant) = info.variant("C").unwrap() {
|
|
assert_eq!(
|
|
1,
|
|
variant.field_len(),
|
|
"expected one of the fields to be ignored"
|
|
);
|
|
assert!(variant.field_at(0).unwrap().is::<bool>());
|
|
} else {
|
|
panic!("expected `VariantInfo::Struct`");
|
|
}
|
|
} else {
|
|
panic!("expected `TypeInfo::Enum`");
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_allow_generics() {
|
|
#[derive(Reflect, Debug, PartialEq)]
|
|
enum TestEnum<T: FromReflect> {
|
|
A,
|
|
B(T),
|
|
C { value: T },
|
|
}
|
|
|
|
if let TypeInfo::Enum(info) = TestEnum::<f32>::type_info() {
|
|
if let VariantInfo::Tuple(variant) = info.variant("B").unwrap() {
|
|
assert!(variant.field_at(0).unwrap().is::<f32>());
|
|
} else {
|
|
panic!("expected `VariantInfo::Struct`");
|
|
}
|
|
if let VariantInfo::Struct(variant) = info.variant("C").unwrap() {
|
|
assert!(variant.field("value").unwrap().is::<f32>());
|
|
} else {
|
|
panic!("expected `VariantInfo::Struct`");
|
|
}
|
|
} else {
|
|
panic!("expected `TypeInfo::Enum`");
|
|
}
|
|
|
|
let mut value = TestEnum::<f32>::A;
|
|
|
|
// === Tuple === //
|
|
let mut data = DynamicTuple::default();
|
|
data.insert(1.23_f32);
|
|
let dyn_enum = DynamicEnum::new("B", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(TestEnum::B(1.23), value);
|
|
|
|
// === Struct === //
|
|
let mut data = DynamicStruct::default();
|
|
data.insert("value", 1.23_f32);
|
|
let dyn_enum = DynamicEnum::new("C", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(TestEnum::C { value: 1.23 }, value);
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_allow_struct_fields() {
|
|
#[derive(Reflect, Debug, PartialEq)]
|
|
enum TestEnum {
|
|
A,
|
|
B(TestStruct),
|
|
C { value: TestStruct },
|
|
}
|
|
|
|
#[derive(Reflect, Debug, PartialEq)]
|
|
struct TestStruct(usize);
|
|
|
|
let mut value = TestEnum::A;
|
|
|
|
// === Tuple === //
|
|
let mut data = DynamicTuple::default();
|
|
data.insert(TestStruct(123));
|
|
let dyn_enum = DynamicEnum::new("B", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(TestEnum::B(TestStruct(123)), value);
|
|
|
|
// === Struct === //
|
|
let mut data = DynamicStruct::default();
|
|
data.insert("value", TestStruct(123));
|
|
let dyn_enum = DynamicEnum::new("C", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(
|
|
TestEnum::C {
|
|
value: TestStruct(123)
|
|
},
|
|
value
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_allow_nesting_enums() {
|
|
#[derive(Reflect, Debug, PartialEq)]
|
|
enum TestEnum {
|
|
A,
|
|
B(OtherEnum),
|
|
C { value: OtherEnum },
|
|
}
|
|
|
|
#[derive(Reflect, Debug, PartialEq)]
|
|
enum OtherEnum {
|
|
A,
|
|
B(usize),
|
|
C { value: f32 },
|
|
}
|
|
|
|
let mut value = TestEnum::A;
|
|
|
|
// === Tuple === //
|
|
let mut data = DynamicTuple::default();
|
|
data.insert(OtherEnum::B(123));
|
|
let dyn_enum = DynamicEnum::new("B", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(TestEnum::B(OtherEnum::B(123)), value);
|
|
|
|
// === Struct === //
|
|
let mut data = DynamicStruct::default();
|
|
data.insert("value", OtherEnum::C { value: 1.23 });
|
|
let dyn_enum = DynamicEnum::new("C", data);
|
|
value.apply(&dyn_enum);
|
|
assert_eq!(
|
|
TestEnum::C {
|
|
value: OtherEnum::C { value: 1.23 }
|
|
},
|
|
value
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_apply() {
|
|
let mut value: Box<dyn Reflect> = Box::new(MyEnum::A);
|
|
|
|
// === MyEnum::A -> MyEnum::A === //
|
|
value.apply(&MyEnum::A);
|
|
assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
|
|
|
|
// === MyEnum::A -> MyEnum::B === //
|
|
value.apply(&MyEnum::B(123, 321));
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::B(123, 321))
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::B -> MyEnum::B === //
|
|
value.apply(&MyEnum::B(321, 123));
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::B(321, 123))
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::B -> MyEnum::C === //
|
|
value.apply(&MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true,
|
|
});
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true
|
|
})
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::C -> MyEnum::C === //
|
|
value.apply(&MyEnum::C {
|
|
foo: 3.21,
|
|
bar: false,
|
|
});
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::C {
|
|
foo: 3.21,
|
|
bar: false
|
|
})
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::C -> MyEnum::B === //
|
|
value.apply(&MyEnum::B(123, 321));
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::B(123, 321))
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::B -> MyEnum::A === //
|
|
value.apply(&MyEnum::A);
|
|
assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_set() {
|
|
let mut value: Box<dyn Reflect> = Box::new(MyEnum::A);
|
|
|
|
// === MyEnum::A -> MyEnum::A === //
|
|
value.set(Box::new(MyEnum::A)).unwrap();
|
|
assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
|
|
|
|
// === MyEnum::A -> MyEnum::B === //
|
|
value.set(Box::new(MyEnum::B(123, 321))).unwrap();
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::B(123, 321))
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::B -> MyEnum::B === //
|
|
value.set(Box::new(MyEnum::B(321, 123))).unwrap();
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::B(321, 123))
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::B -> MyEnum::C === //
|
|
value
|
|
.set(Box::new(MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true,
|
|
}))
|
|
.unwrap();
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::C {
|
|
foo: 1.23,
|
|
bar: true
|
|
})
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::C -> MyEnum::C === //
|
|
value
|
|
.set(Box::new(MyEnum::C {
|
|
foo: 3.21,
|
|
bar: false,
|
|
}))
|
|
.unwrap();
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::C {
|
|
foo: 3.21,
|
|
bar: false
|
|
})
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::C -> MyEnum::B === //
|
|
value.set(Box::new(MyEnum::B(123, 321))).unwrap();
|
|
assert!(value
|
|
.reflect_partial_eq(&MyEnum::B(123, 321))
|
|
.unwrap_or_default());
|
|
|
|
// === MyEnum::B -> MyEnum::A === //
|
|
value.set(Box::new(MyEnum::A)).unwrap();
|
|
assert!(value.reflect_partial_eq(&MyEnum::A).unwrap_or_default());
|
|
}
|
|
|
|
#[test]
|
|
fn enum_should_partial_eq() {
|
|
#[derive(Reflect)]
|
|
enum TestEnum {
|
|
A,
|
|
A1,
|
|
B(usize),
|
|
B1(usize),
|
|
B2(usize, usize),
|
|
C { value: i32 },
|
|
C1 { value: i32 },
|
|
C2 { value: f32 },
|
|
}
|
|
|
|
let a: &dyn Reflect = &TestEnum::A;
|
|
let b: &dyn Reflect = &TestEnum::A;
|
|
assert!(
|
|
a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::A == TestEnum::A"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::A;
|
|
let b: &dyn Reflect = &TestEnum::A1;
|
|
assert!(
|
|
!a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::A != TestEnum::A1"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::B(123);
|
|
let b: &dyn Reflect = &TestEnum::B(123);
|
|
assert!(
|
|
a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::B(123) == TestEnum::B(123)"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::B(123);
|
|
let b: &dyn Reflect = &TestEnum::B(321);
|
|
assert!(
|
|
!a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::B(123) != TestEnum::B(321)"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::B(123);
|
|
let b: &dyn Reflect = &TestEnum::B1(123);
|
|
assert!(
|
|
!a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::B(123) != TestEnum::B1(123)"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::B(123);
|
|
let b: &dyn Reflect = &TestEnum::B2(123, 123);
|
|
assert!(
|
|
!a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::B(123) != TestEnum::B2(123, 123)"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::C { value: 123 };
|
|
let b: &dyn Reflect = &TestEnum::C { value: 123 };
|
|
assert!(
|
|
a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::C{{value: 123}} == TestEnum::C{{value: 123}}"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::C { value: 123 };
|
|
let b: &dyn Reflect = &TestEnum::C { value: 321 };
|
|
assert!(
|
|
!a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::C{{value: 123}} != TestEnum::C{{value: 321}}"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::C { value: 123 };
|
|
let b: &dyn Reflect = &TestEnum::C1 { value: 123 };
|
|
assert!(
|
|
!a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::C{{value: 123}} != TestEnum::C1{{value: 123}}"
|
|
);
|
|
|
|
let a: &dyn Reflect = &TestEnum::C { value: 123 };
|
|
let b: &dyn Reflect = &TestEnum::C2 { value: 1.23 };
|
|
assert!(
|
|
!a.reflect_partial_eq(b).unwrap_or_default(),
|
|
"expected TestEnum::C{{value: 123}} != TestEnum::C2{{value: 1.23}}"
|
|
);
|
|
}
|
|
}
|