rust-lang / style-team

Home of the Rust style team
Apache License 2.0
454 stars 56 forks source link

Closures with complex arguments #138

Open topecongiro opened 5 years ago

topecongiro commented 5 years ago

In #35 the discussion was mainly about how we format the body of closures. Currently rustfmt uses visual indent when we need to use multiple lines for closure's arguments:

fn examples() {
    let commented = |// first
                     a, // argument
                     // second
                     b: WithType, // argument
                     // ignored
                     _| {
         (a, b)
     };

    let block_body = move |xxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
                           ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy| {
        xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
    };

    let y = x.into_iter().map(
        |AaaaaaAaaaaaaaaaa {
             bbbbbb_bbbb,
             ccc_ccccccc,
         }| (),
    );
}

Since the default indent style in other places is block indent, I was wondering where rustfmt should use it in closure's arguments as well:

fn examples() {
    let y = x.into_iter().map(
        |
            AaaaaaAaaaaaaaaaa {
                bbbbbb_bbbb,
                ccc_ccccccc,
            },
        | (),
    );

    let commented = |
        // first
        a, // argument
        // second
        b: WithType, // argument
        // ignored
        _,
    | {
        (
            aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
            bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb,
        )
    };

    let block_body = move |
        xxxxxxxxxxxxxxxxxxxxxxxxxxxxx,
        ref yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy,
    | {
        xxxxxxxxxxxxxxxxxxxxxxxxxxxxx + yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
    };
}

Any thoughts?

purpleposeidon commented 5 years ago

Figuring out how to format closures has been driving me slightly bonkers. And vim doesn't have any appreciation for visually indenting the arguments. Treating them as a fn item declaration may be the sanest approach, and would be consistent with the rest of Rust. It'd be nice if they just had a more compliant syntax, but that ship has already sailed, sunken off the coast of Costa Rica, and been salvaged as a source for metal free from the radioactive contamination of nuclear testing.

joshtriplett commented 5 years ago

With my format team hat on: I do think we should use block style for closures. I also think we should treat the leading | and trailing | -> Type the same way we treat other grouping, so that we can put the | on the same line as the start of a function accepting the closure as an argument.

Would someone be up for writing a PR for the style guide?

dullbananas commented 1 year ago

The current style can have a disgusting result:

let read = move |mut conn: DbConn<'a>,
                 (post_id, my_person_id, is_mod_or_admin): (
  PostId,
  Option<PersonId>,
  Option<bool>,
)| async move {
joshtriplett commented 1 year ago

I don't think that's consistent with the style guide, or at least I don't know what rule would produce that result.

cc @rust-lang/rustfmt

calebcartwright commented 1 year ago

The current style can have a disgusting result:

let read = move |mut conn: DbConn<'a>,
                 (post_id, my_person_id, is_mod_or_admin): (
  PostId,
  Option<PersonId>,
  Option<bool>,
)| async move {

This is due to a very long standing bug in rustfmt and as Josh noted, does not adhere to the style guide prescriptions for closures

https://github.com/rust-lang/rustfmt/issues/3865

musjj commented 7 months ago

This issue has been bugging me too. Anyone working on it?

I wonder if a separate option should be added (like imports_indent) or should indent_style be extended for closures too? The former might be preferable for backwards-compatibility.