Multiple Line `fn` and `impl` Declarations

So I’m looking at the rust style guide, and something came off as weird to me. In whitespace, it says that a multiple line function definition is written as:

fn frobnicate(a: Bar, b: Bar,
              c: Bar, d: Bar)  // Note that these definitions are lined up
              -> Bar {  // with the previous lines
    ...
}

whereas multiple lines of variables (i.e. in structs) are written as:

struct Bar {
    short: f64,  // Note that the type names are differently aligned
    really_long: f64,
}

because names can change. This seems like a disconnect; in one case, we have the function definition’s variables being aligned to the function name, and in the other, they are aligned to the correct indentation. I think we should change this to

fn frobnicate(a: Bar, b: Bar,
        c: Bar, d: Bar) -> Bar {
    ...
}

or

fn frobnicate(a: Bar, b: Bar,
        c: Bar, d: Bar)
        -> Bar {
    ...
}

which I think seems more consistent. It’s also nice for multiline impls, as in this commit to rust-by-example, where:

impl<T: Add<T, T>> Add<Vec2<T>, Vec2<T>>
        for Vec2<T> {
    fn add(...) {
        ...
    }
}

or

impl<T> Sub<Vec2<T>, Vec2<T>> for Vec2<T>
        where T: Sub<T, T> {
    ...
}

is used.

N.B. The reason I use two tabs to indent instead of one, is:

fn do_the_thing(a: A, b: B,
    c: C, d: D) {
    ...
}

You can’t really tell where the code starts and the args end.

1 Like

I have also found this really useful in a real world case:

fn read_to_vec<T, F>(&mut self, mut f: F) -> Result<Vec<T>, E>
        where F: FnMut(&mut D) -> Result<T, E> {

with closures. There is a clear separation between the function itself, and the closure that the function takes.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.