You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi @jbaublitz, thanks for this fantastic crate! I have a few ideas for improving the Getter/MutGetter macros and would love to hear your thoughts.
Motivation
When a struct field is an Option<T> or Result<T, E>, the generated getter currently returns &Option<T> or &Result<T, E>. In many cases, it’s more ergonomic to return Option<&T> or Result<&T, &E> instead:
Calling .as_ref() (or .as_mut()) lets users work directly with borrowed inner data without cloning the container.
Clippy recommends preferring Option<&T> over &Option<T> for performance and readability (clippy::ref_option).
Proposal
Add two optional parameters to the attribute syntax:
get = "as_ref"
get_mut = "as_mut"
When applied, the macro expansion will call the corresponding method:
By making as_ref/as_mut opt-in, existing derives remain unchanged.
No breaking changes to public APIs unless users explicitly opt in.
Additional Thoughts
Generalizing to all AsRef types:
It would be nice to auto-apply .as_ref() on any field whose type implements AsRef, but detecting arbitrary trait implementations in a procedural macro is nontrivial without compiler context.
Attribute parsing robustness:
I noticed that multiple #[getset(...)] attributes on the same item only respect the last one (due to using filter_map(...).next_back() in parsing). For example:
only the final #[getset(get)] takes effect. We might consider using a helper like darling to simplify and harden attribute parsing; I’m happy to help integrate it.
Thank you for considering these enhancements—I look forward to your feedback!
Hi @jbaublitz, thanks for this fantastic crate! I have a few ideas for improving the
Getter/MutGettermacros and would love to hear your thoughts.Motivation
When a struct field is an
Option<T>orResult<T, E>, the generated getter currently returns&Option<T>or&Result<T, E>. In many cases, it’s more ergonomic to returnOption<&T>orResult<&T, &E>instead:.as_ref()(or.as_mut()) lets users work directly with borrowed inner data without cloning the container.Option<&T>over&Option<T>for performance and readability (clippy::ref_option).Proposal
Add two optional parameters to the attribute syntax:
get = "as_ref"get_mut = "as_mut"When applied, the macro expansion will call the corresponding method:
generates:
All other fields without these options continue to generate
&Option<T>/&Result<T, E>as before, ensuring full backward compatibility.Implementation
I’ve drafted a proof-of-concept PR that:
get = "as_ref"andget_mut = "as_mut"in addition to existing options..as_ref()or.as_mut()into the getter body when specified.Feel free to review it here: [#120].
Backward Compatibility
as_ref/as_mutopt-in, existing derives remain unchanged.Additional Thoughts
Generalizing to all
AsReftypes:It would be nice to auto-apply
.as_ref()on any field whose type implementsAsRef, but detecting arbitrary trait implementations in a procedural macro is nontrivial without compiler context.Community interest:
Similar requests have appeared in issues [Provide ability to create getters that return
A<&T>instead of&A<T>#78], [Fix problems with global attributes and implements getter/setter for Option<T> #83], and [feat: addinto,optional,as_ref,as_mutandconstoptions #117], but were held back by breaking-change concerns. Because this proposal is fully opt-in and backward-compatible, I believe it addresses past objections and could gain community support.Attribute parsing robustness:
I noticed that multiple
#[getset(...)]attributes on the same item only respect the last one (due to usingfilter_map(...).next_back()in parsing). For example:only the final
#[getset(get)]takes effect. We might consider using a helper like darling to simplify and harden attribute parsing; I’m happy to help integrate it.Thank you for considering these enhancements—I look forward to your feedback!