Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for impl Trait inside #[component] params #2274

Closed
mscofield0 opened this issue Feb 7, 2024 · 5 comments · Fixed by #2599
Closed

Support for impl Trait inside #[component] params #2274

mscofield0 opened this issue Feb 7, 2024 · 5 comments · Fixed by #2599

Comments

@mscofield0
Copy link

Is your feature request related to a problem? Please describe.
It's sort of annoying having to specify generic args on a component that has a lot of views.
e.g.

#[component]
fn Foo<T, IV1, IVF1, IV2, IVF2, IV3, IVF3, IV4, IVF4>(
    v1: IVF1,
    v2: IVF2,
    v3: IVF3,
    v4: IVF4,
) -> impl IntoView
where
    IV1: IntoView,
    IV2: IntoView,
    IV3: IntoView,
    IV4: IntoView,
    IVF1: Fn(T) -> IV1 + 'static,
    IVF2: Fn(T) -> IV2 + 'static,
    IVF3: Fn(T) -> IV3 + 'static,
    IVF4: Fn(T) -> IV4 + 'static,
{...}

Describe the solution you'd like
I would like to write my components like this:

#[component]
fn Foo<T, IV1, IV2, IV3, IV4>(
    v1: impl Fn(T) -> IV1,
    v2: impl Fn(T) -> IV2,
    v3: impl Fn(T) -> IV3,
    v4: impl Fn(T) -> IV4,
) -> impl IntoView
where
    IV1: IntoView,
    IV2: IntoView,
    IV3: IntoView,
    IV4: IntoView,
{...}

or even

#[component]
fn Foo<T>(
    v1: impl Fn(T) -> View,
    v2: impl Fn(T) -> View,
    v3: impl Fn(T) -> View,
    v4: impl Fn(T) -> View,
) -> impl IntoView
{...}

if I'm feeling particularly lazy.

Describe alternatives you've considered
The alternatives are just continue using the standard way of doing it.

@gbj
Copy link
Collaborator

gbj commented Feb 8, 2024

The props are built into a struct with a typed builder, since Rust doesn't support named/keyword arguments for functions. As a result, this

fn Foo<T, IV1, IVF1, IV2, IVF2, IV3, IVF3, IV4, IVF4>(
    v1: IVF1,
    v2: IVF2,
    v3: IVF3,
    v4: IVF4,
) -> impl IntoView
where
    IV1: IntoView,
    IV2: IntoView,
    IV3: IntoView,
    IV4: IntoView,
    IVF1: Fn(T) -> IV1 + 'static,
    IVF2: Fn(T) -> IV2 + 'static,
    IVF3: Fn(T) -> IV3 + 'static,
    IVF4: Fn(T) -> IV4 + 'static,

can relatively easily be rewritten to

struct FooProps<T, IV1, IVF1, IV2, IVF2, IV3, IVF3, IV4, IVF4> {
    v1: IVF1,
    v2: IVF2,
    v3: IVF3,
    v4: IVF4,
}
where
    IV1: IntoView,
    IV2: IntoView,
    IV3: IntoView,
    IV4: IntoView,
    IVF1: Fn(T) -> IV1 + 'static,
    IVF2: Fn(T) -> IV2 + 'static,
    IVF3: Fn(T) -> IV3 + 'static,
    IVF4: Fn(T) -> IV4 + 'static,

because there is a 1:1 relationship between the generics, parameters/field names, and where clause between functions and structs.

It is much harder to do this with

fn Foo<T, IV1, IV2, IV3, IV4>(
    v1: impl Fn(T) -> IV1,
    v2: impl Fn(T) -> IV2,
    v3: impl Fn(T) -> IV3,
    v4: impl Fn(T) -> IV4,
) -> impl IntoView
where
    IV1: IntoView,
    IV2: IntoView,
    IV3: IntoView,
    IV4: IntoView,
{...}

because there is no support for "impl trait in struct definition," so the #[component] macro would have to do a significant amount of work expand the impl parameters into additional generics, both in the initial generic list and in the where clause.

Hence why this has not been added.

Is it something you might be interested in working on?

@mscofield0
Copy link
Author

mscofield0 commented Feb 9, 2024

On second thought, I don't think it's particularly worth the additional complexity and compile time performance.

@MingweiSamuel
Copy link
Contributor

MingweiSamuel commented May 21, 2024

impl trait in struct definition," so the #[component] macro would have to do a significant amount of work expand the impl parameters into additional generics, both in the initial generic list and in the where clause.

This seems... not that hard? Just generate an extra generic name for each impl Trait and substitute in? Am I missing something or should I go for a PR?

@gbj
Copy link
Collaborator

gbj commented May 21, 2024

@MingweiSamuel Go for a PR!

@MingweiSamuel
Copy link
Contributor

MingweiSamuel commented May 21, 2024

Easiest strategy is to pre-process the signature to remove impl Trait, taking it from a valid rust ItemFn to a valid rust ItemFn without touching any leptos logic:

https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=148cd62ecddec64b83ed12838cf0f5cd

Ok to just add that^? (Ill optimize a bit. Could also generate more descriptive generic param names). Could even feature flag it with one line if wanted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants