From fcbbef965b4b260fc64116aa926526ffea9087bb Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 20 Oct 2025 20:01:39 +0000 Subject: [PATCH 1/3] Remove blanket implementation of HasField --- crates/cgp-field/src/traits/has_field.rs | 40 ++++++++------------ crates/cgp-field/src/traits/has_field_mut.rs | 9 ++--- 2 files changed, 18 insertions(+), 31 deletions(-) diff --git a/crates/cgp-field/src/traits/has_field.rs b/crates/cgp-field/src/traits/has_field.rs index fb966a08..b5707da2 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<'a, Context, Tag, Value> HasField for &'a 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<'a, Context, Tag, Value> HasField for &'a 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..eb4402b7 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<'a, Context, Tag, Value> HasFieldMut for &'a 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) } } From 27fd0672b9c56d3f99c42d7030edf15daa7f8012 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 20 Oct 2025 20:12:15 +0000 Subject: [PATCH 2/3] Add tests for bulk forwarding of HasField --- .../src/tests/has_field/forward_inner.rs | 78 +++++++++++++++++++ crates/cgp-tests/src/tests/has_field/mod.rs | 1 + 2 files changed, 79 insertions(+) create mode 100644 crates/cgp-tests/src/tests/has_field/forward_inner.rs 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; From ededcc9fdf115993346ab4338bace727efc43137 Mon Sep 17 00:00:00 2001 From: Soares Chen Date: Mon, 20 Oct 2025 20:12:40 +0000 Subject: [PATCH 3/3] Fix clippy --- crates/cgp-field/src/traits/has_field.rs | 4 ++-- crates/cgp-field/src/traits/has_field_mut.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/cgp-field/src/traits/has_field.rs b/crates/cgp-field/src/traits/has_field.rs index b5707da2..3495da5e 100644 --- a/crates/cgp-field/src/traits/has_field.rs +++ b/crates/cgp-field/src/traits/has_field.rs @@ -69,7 +69,7 @@ where } } -impl<'a, Context, Tag, Value> HasField for &'a Context +impl HasField for &Context where Context: HasField, { @@ -80,7 +80,7 @@ where } } -impl<'a, Context, Tag, Value> HasField for &'a mut Context +impl HasField for &mut Context where Context: HasField, { diff --git a/crates/cgp-field/src/traits/has_field_mut.rs b/crates/cgp-field/src/traits/has_field_mut.rs index eb4402b7..939d4d7c 100644 --- a/crates/cgp-field/src/traits/has_field_mut.rs +++ b/crates/cgp-field/src/traits/has_field_mut.rs @@ -14,7 +14,7 @@ pub trait MutFieldGetter: FieldGetter { fn get_field_mut(context: &mut Context, tag: PhantomData) -> &mut Self::Value; } -impl<'a, Context, Tag, Value> HasFieldMut for &'a mut Context +impl HasFieldMut for &mut Context where Context: HasFieldMut, {