Customizing `use` style with rustfmt

One of the things I find rather problematic about rustfmt, as with all prescriptive formatting tools, is the way that its prescriptive nature tends to enforce mixing stylistic with functional changes.

A particular bugbear in this respect is use statements. I generally find that it's convenient to try to split these across lines so as to make for clean and clear diffs when an import is added or removed. Given Rust's nested use syntax, the style I've found to be the best compromise between conciseness is something like this:

use serde::{Deserialize, Serialize};
use std::{
    cell::RefCell,
    collections::HashSet,
    iter::FromIterator
};
use tonic::{
    transport::Channel,
    Request, Response, Status
};

In other words:

  • one line per module (or submodule)
  • individual symbols can be on the same line (with the assumption that there will be few of them per module)
  • if the number of symbols per module is large, use { ... } to break them over several lines

This means that generally speaking, if an import needs to be added or removed, the diff is clean, clear, and simple.

However, rustfmt insists on trying to rewrite this to minimize the number of vertical lines used. For example, to:

use serde::{Deserialize, Serialize};
use std::{cell::RefCell, collections::HashSet, iter::FromIterator};
use tonic::{transport::Channel, Request, Response, Status};

Note that this happens even with imports_layout = "HorizontalVertical", as this style will still try to put everything on one line if it can.

Why does this matter? Well, apart from the fact that (to me) it's less easy to grok what belongs to what, it also means that if (for example) I have a longer list of imports from std, and then remove one of them, the style of the imports can get rewritten at the same time as the import is removed. This means that I have to choose between either committing code that is in breach of what rustfmt wants, or to commit a diff where it's much harder to see what has meaningfully changed.

I could just use Vertical style, with a single symbol per line, but that seems a little excessive. I guess that what I'm looking for is a style that is Vertical for (sub)modules but HorizontalVertical for symbols.

Can anyone advise on whether it's possible to achieve the multi-line style I'm looking for with current rustfmt options? And if not, does it seem reasonable to put in a feature request?

I note that I would probably settle for an option that makes rustfmt less intrusive, i.e. where it only rewrites if there is an explicit violation of style requirements, rather than trying to prescriptively impose One True Way. But obviously that may not be what people want in the tool :wink:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.