Rust Formatter (rustfmt)

Paste Rust source and get the layout `cargo fmt` would produce. rustfmt runs as WebAssembly inside this tab, so your code is never sent to a server.

Input

Settings

History

Load from URL

What the Rust formatter does

This page runs rustfmt (WASM), the same formatter that cargo fmt invokes, compiled for the browser. It parses your file with the Rust compiler’s own parser and reprints it using the 2021 edition and the 2021 style edition, with Unix line endings.

rustfmt changes layout, not meaning. Expect it to:

  • put one statement per line and expand blocks, match arms and struct literals
  • break long method chains so each .call() starts its own line
  • add trailing commas to multi-line struct fields, enum variants and match arms
  • sort use declarations and mod items alphabetically, as cargo fmt does by default

Comments and doc comments (///, //!) are kept where you wrote them. The formatter does not type-check or borrow-check anything, so code that would fail cargo build still formats as long as it parses.

Indentation, width and shortcuts

There are no Rust-only switches; the toolbar’s indent and line-width settings map straight onto rustfmt’s tab_spaces, hard_tabs and max_width. One thing catches people out: rustfmt’s own defaults are 4 spaces and 100 columns, while the toolbar opens at 2 spaces and 80. Pick 4 and 100 if the output should match an unconfigured cargo fmt run in CI. A rustfmt.toml from your project is not read, so options like imports_granularity or group_imports cannot be applied here.

Press Ctrl/Cmd+Enter to format, Ctrl/Cmd+Shift+C to copy the result and Ctrl/Cmd+K to jump to another formatter from the command palette. Ctrl/Cmd+Shift+M is the minify shortcut, but Rust has no minified form, so it is not offered on this page.

Macros, errors and other edge cases

Macro calls written with parentheses or square brackets, such as println!(...) or vec![...], are formatted like function calls. Brace-delimited macros (html! { ... }, macro_rules! bodies) are left almost untouched because rustfmt cannot know their grammar.

If the file does not parse, nothing is reformatted: you get the compiler’s message with a line and column instead of half-formatted output. An unclosed delimiter is reported where the file ends, not where the brace was opened, so scan upwards from the last block you edited. Very deep nesting or an unterminated string can make the WebAssembly build abort with a “crashed” message rather than a tidy diagnostic.

Generated code from build.rs or include! files formats fine, which is handy when you need to read what a derive or code generator actually produced. The same goes for the output of cargo expand: paste it here to turn one enormous line of expanded macro code into something you can follow.

Attributes such as #[derive(Debug, Clone)] move onto their own line above the item, and rustfmt normalises spacing inside them. If you want a block left exactly as written, put #[rustfmt::skip] on the item; the formatter honours it here just as it does locally.

Examples

Method chain with the ? operator

The chain is split one call per line, and the struct literal gains a trailing comma after its last field.

Input
impl Config{pub fn from_env()->Result<Self,String>{let port=std::env::var("PORT").unwrap_or_else(|_|"8080".into()).parse::<u16>().map_err(|e|e.to_string())?;Ok(Self{port,debug:cfg!(debug_assertions)})}}
Output
impl Config {
    pub fn from_env() -> Result<Self, String> {
        let port = std::env::var("PORT")
            .unwrap_or_else(|_| "8080".into())
            .parse::<u16>()
            .map_err(|e| e.to_string())?;
        Ok(Self {
            port,
            debug: cfg!(debug_assertions),
        })
    }
}
Open this example in the tool

Enum and match arms

Short struct variants stay on one line; every match arm gets its own line and a trailing comma.

Input
enum Shape{Circle{r:f64},Rect{w:f64,h:f64}}
fn area(s:&Shape)->f64{match s{Shape::Circle{r}=>std::f64::consts::PI*r*r,Shape::Rect{w,h}=>w*h}}
Output
enum Shape {
    Circle { r: f64 },
    Rect { w: f64, h: f64 },
}
fn area(s: &Shape) -> f64 {
    match s {
        Shape::Circle { r } => std::f64::consts::PI * r * r,
        Shape::Rect { w, h } => w * h,
    }
}
Open this example in the tool

Generic function with a where clause, 4-space indent

With the indent set to 4, the output matches a default cargo fmt run, including the where clause on its own lines.

Input
pub fn largest<T>(items:&[T])->Option<&T> where T:PartialOrd{let mut it=items.iter();let mut best=it.next()?;for x in it{if x>best{best=x;}}Some(best)}
Output
pub fn largest<T>(items: &[T]) -> Option<&T>
where
    T: PartialOrd,
{
    let mut it = items.iter();
    let mut best = it.next()?;
    for x in it {
        if x > best {
            best = x;
        }
    }
    Some(best)
}
Open this example in the tool

Common errors and how to fix them

ErrorCauseFix
this file contains an unclosed delimiterA (, [ or { was opened and never closed. The parser only notices at the end of the file.Work backwards from the last function you changed and count braces; the highlighted position is where the parser gave up, not where the brace is missing.
unexpected closing delimiter: `}`There is one closing brace (or bracket) too many, often left behind after deleting a block.Remove the stray } at the reported column, or restore the opening line that was deleted.
expected `,`, or `}`, found `b`Two struct fields, enum variants or struct-literal entries are not separated by a comma.Add a comma after the field before the reported token.
expected type, found `{`A -> is followed by the function body instead of a return type.Write the return type after the arrow (for example -> i32) or drop the arrow for functions that return ().
rustfmt crashed while formatting. This is usually deeply nested source exhausting the module's stack.The WebAssembly build aborted instead of returning a diagnostic. An unterminated string literal or extremely deep nesting are the usual triggers.Check that every " is closed, then split very deep expressions into smaller functions and format again.

Frequently asked questions

Is the output identical to cargo fmt?

It is the same rustfmt code, so with the same settings the output is the same. Set the indent to 4 and the line width to 100 to mirror rustfmt defaults; the page starts at 2 and 80.

Does it read my rustfmt.toml?

No. Only indentation, tabs and maximum width can be changed. Unstable options such as imports_granularity need a local nightly rustfmt.

Which Rust edition does it parse?

Edition 2021, with the 2021 style edition. Syntax from older editions parses too; edition-2024-only syntax may be rejected.

Will formatting change what my program does?

No. rustfmt only moves whitespace, reorders imports and adds or removes trailing commas, none of which changes the compiled program.

Can it find type or borrow-checker errors?

No. It parses the code but never compiles it, so only syntax errors are reported. Use cargo check or rust-analyzer for type errors.

Related tools