diff --git a/crates/cgp-field/src/traits/has_field.rs b/crates/cgp-field/src/traits/has_field.rs index fb966a08..3495da5e 100644 --- a/crates/cgp-field/src/traits/has_field.rs +++ b/crates/cgp-field/src/traits/has_field.rs @@ -1,5 +1,4 @@ use core::marker::PhantomData; -use core::ops::Deref; use cgp_component::UseContext; @@ -59,19 +58,6 @@ pub trait FieldGetter { fn get_field(context: &Context, _tag: PhantomData) -> &Self::Value; } -#[diagnostic::do_not_recommend] -impl HasField for Context -where - Context: DerefMap, - Target: HasField, -{ - type Value = Value; - - fn get_field(&self, tag: PhantomData) -> &Self::Value { - self.map_deref(|context| context.get_field(tag)) - } -} - impl FieldGetter for UseContext where Context: HasField, @@ -83,20 +69,24 @@ where } } -/** - A helper trait to help organize the lifetime inference in Rust. - Without this, `Self::Target` would need to be `'static`, as Rust couldn't - infer the correct lifetime when calling `context.deref().get_field()`. -*/ -trait DerefMap: Deref { - fn map_deref(&self, mapper: impl for<'a> FnOnce(&'a Self::Target) -> &'a T) -> &T; +impl HasField for &Context +where + Context: HasField, +{ + type Value = Value; + + fn get_field(&self, tag: PhantomData) -> &Self::Value { + Context::get_field(self, tag) + } } -impl DerefMap for Context +impl HasField for &mut Context where - Context: Deref, + Context: HasField, { - fn map_deref(&self, mapper: impl for<'a> FnOnce(&'a Self::Target) -> &'a T) -> &T { - mapper(self.deref()) + type Value = Value; + + fn get_field(&self, tag: PhantomData) -> &Self::Value { + Context::get_field(self, tag) } } diff --git a/crates/cgp-field/src/traits/has_field_mut.rs b/crates/cgp-field/src/traits/has_field_mut.rs index e47f393c..939d4d7c 100644 --- a/crates/cgp-field/src/traits/has_field_mut.rs +++ b/crates/cgp-field/src/traits/has_field_mut.rs @@ -1,5 +1,4 @@ use core::marker::PhantomData; -use core::ops::DerefMut; use crate::traits::{FieldGetter, HasField}; @@ -15,13 +14,11 @@ pub trait MutFieldGetter: FieldGetter { fn get_field_mut(context: &mut Context, tag: PhantomData) -> &mut Self::Value; } -#[diagnostic::do_not_recommend] -impl HasFieldMut for Context +impl HasFieldMut for &mut Context where - Context: DerefMut, - Target: HasFieldMut + 'static, + Context: HasFieldMut, { fn get_field_mut(&mut self, tag: PhantomData) -> &mut Self::Value { - self.deref_mut().get_field_mut(tag) + Context::get_field_mut(self, tag) } } diff --git a/crates/cgp-tests/src/tests/has_field/forward_inner.rs b/crates/cgp-tests/src/tests/has_field/forward_inner.rs new file mode 100644 index 00000000..5748e353 --- /dev/null +++ b/crates/cgp-tests/src/tests/has_field/forward_inner.rs @@ -0,0 +1,78 @@ +use cgp::prelude::*; + +#[derive(HasField)] +pub struct Foo { + pub foo_value: String, + pub bar: Bar, +} + +#[derive(HasField)] +pub struct Bar { + pub bar_value: u64, + pub baz: Baz, +} + +#[derive(HasField)] +pub struct Baz { + pub baz_value: i32, +} + +impl HasField for Foo +where + Bar: HasField, +{ + type Value = Value; + + fn get_field(&self, tag: PhantomData) -> &Self::Value { + self.bar.get_field(tag) + } +} + +impl HasField for Bar +where + Baz: HasField, +{ + type Value = Value; + + fn get_field(&self, tag: PhantomData) -> &Self::Value { + self.baz.get_field(tag) + } +} + +#[cgp_auto_getter] +pub trait HasFooValue { + fn foo_value(&self) -> &str; +} + +#[cgp_auto_getter] +pub trait HasBarValue { + fn bar_value(&self) -> u64; +} + +#[cgp_auto_getter] +pub trait HasBazValue { + fn baz_value(&self) -> i32; +} + +#[test] +fn test_bulk_forward_has_field() { + let context = Foo { + foo_value: "hello".to_owned(), + bar: Bar { + bar_value: 42, + baz: Baz { baz_value: 128 }, + }, + }; + + assert_eq!( + context.get_field(PhantomData::), + "hello" + ); + assert_eq!(context.foo_value(), "hello"); + + assert_eq!(context.get_field(PhantomData::), &42); + assert_eq!(context.bar_value(), 42); + + assert_eq!(context.get_field(PhantomData::), &128); + assert_eq!(context.baz_value(), 128); +} diff --git a/crates/cgp-tests/src/tests/has_field/mod.rs b/crates/cgp-tests/src/tests/has_field/mod.rs index 54d09ba3..47a79857 100644 --- a/crates/cgp-tests/src/tests/has_field/mod.rs +++ b/crates/cgp-tests/src/tests/has_field/mod.rs @@ -1,3 +1,4 @@ pub mod chain; +pub mod forward_inner; pub mod index; pub mod life;