Skip to content

Conversation

zakstucke
Copy link
Contributor

@zakstucke zakstucke commented Aug 31, 2025

Love the library!

This PR adds a transform_generics config to allow adding generic parameters and lifetimes to the closure provided by #[builder(setter(transform = "..."))]

The goal is to be able to replicate this setter:

pub fn set_s<M>(s: impl IntoValue<String, M>) -> String {
    s.into_value()
}

And with this PR can be done as:

#[derive(TypedBuilder)]
struct Foo {
    #[builder(
        setter(
            transform_generics = "<__Marker>",
            transform = |value: impl IntoValue<String, __Marker>| value.into_value()
        )
    )]
    s: String,
}

I don't have any preference for this specific syntax, this just seemed to be the simplest non-breaking way to add the functionality, happy to change the implementation if it still adds the same new functionality?

An example of a usecase for this (real usecase in leptos):

struct MBaseCase;

struct MClosure;

trait IntoValue<T, M> {
    fn into_value(self) -> T;
}

impl<T, I> IntoValue<T, MBaseCase> for I
where
    I: Into<T>,
{
    fn into_value(self) -> T {
        self.into()
    }
}

impl<T, F> IntoValue<T, MClosure> for F
where
    F: FnOnce() -> T,
{
    fn into_value(self) -> T {
        self()
    }
}

With this custom transform setter, I can now use either T or || T

@zakstucke
Copy link
Contributor Author

Hi @idanarye, could you please trigger CI when you get a chance? It needs maintainer approval. Thanks!

@zakstucke
Copy link
Contributor Author

Example of new syntax:

    #[derive(TypedBuilder)]
    struct Foo {
        #[builder(
            setter(
                fn transform<'a, M>(value: impl IntoValue<'a, String, M>) -> String
                where
                    M: 'a,
                 {
                    value.into_value()
                },
            )
        )]
        s: String,
    }

Existing closure syntax is still supported, so this would still be a minor release

KeyValue(KeyValue),
Sub(SubAttr),
Not { not: Token![!], name: Ident },
Fn(syn::ItemFn),
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm starting to wonder - maybe instead of ItemFn this should be generalized as an Item? Or would that be too hard to work with?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just tried but it does make it harder to work with, it just requires adding support in a few methods for a lot of variants not currently used. I'd prefer to leave as is unless you feel strongly about it?

@zakstucke zakstucke requested a review from idanarye September 8, 2025 09:24
@zakstucke
Copy link
Contributor Author

Hi @idanarye, this is ready for re-review whenever you're ready :)

@idanarye idanarye merged commit 0267b1a into idanarye:master Sep 14, 2025
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants