Repository: rust
Issue: Feature request: Add a way to capture a formatter that can be passed to format helper functions
Labels: T-libs-api,C-feature-request

### Motivation

The Display trait allows lazy formatting of data. The formatter is passed in and used by the implemented `fmt` function for the struct. Often however applications and libraries want to expose helper functions to compose the display parts of a complex struct.

There are several ways to solve that:

1. Return helper structs from each of those helper functions and implement display for each of them
2. Use a buffer to write the data and pass in a Vec! (but loose all formatting parameters that way)
3. Use internal functions within the fmt() function itself

1) is not always feasible, 2) does use a wasteful extra buffer (which fmt avoids), 3) is possible when the helper functions should be private.

The motivation however here is that not only the Display::fmt function can be called by the user, but also the helper functions to format just parts of the struct (in our use-case different statistics).

The signature of the helper functions is the same as of fmt in the Display trait:

```rust
pub fn fmt_xyz(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
  writeln!(fmt, '{}', self.field_1);
}
```

But it is not possible to construct a formatter manually.

The only way to be able to call the helper function is to use:

The format crate or a helper Fmt() struct, which can capture the formatter passed in.

### Proposed resolution

To solve that I am arguing that either a macro or a Fmt helper trait should be available in core rust so that there exists no function that you just can't call as a user (without an extra crate or helper trait).

The usage looks for example like this:

```
format!("{}", Fmt(|fmt| my_struct.fmt_xyz(fmt)));
```

The implementation of Fmt is as follows:

```rust
pub struct Fmt<F>(pub F) where F: Fn(&mut fmt::Formatter) -> fmt::Result;

impl<F> fmt::Debug for Fmt<F>
    where F: Fn(&mut fmt::Formatter) -> fmt::Result
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        (self.0)(f)
    }
}
```
(from: https://users.rust-lang.org/t/reusing-an-fmt-formatter/8531/3)

### Discussion

I am not sure if `Fmt` is the right name as it feels a little bit weird.

Alternative proposals are like the `format` crate does it using a macro:

```
lazy_format!("{}", |fmt| my_struct.fmt_xyz(fmt));
```

Or what would be great if via some compiler magic a closure could directly work:

```
format!("{}", |fmt| my_struct.fmt_xyz(fmt));
```

From a user experience perspective the last version feels ideal, but I am not sure how difficult it would be to implement that.

### Next steps

- [ ] Discuss if it's possible to add this to rust stdlib
- [ ] Discuss the name / implementation details
- [ ] Create a PR

### Related issues

- As a bug report, but has no detailed implementation plan: https://github.com/rust-lang/rust/issues/46591

### Change scope

The scope is a small addition and hence seemed to not need a RFC per the guide lines.

----------

If this has a chance of going in, I am happy to provide a PR.