Format Rust code

Overview

rustfmt Linux badge Mac badge Windows badge crates.io badge Travis config badge

A tool for formatting Rust code according to style guidelines.

If you'd like to help out (and you should, it's a fun project!), see Contributing.md and our Code of Conduct.

You can use rustfmt in Travis CI builds. We provide a minimal Travis CI configuration (see here) and verify its status using another repository. The status of that repository's build is reported by the "travis example" badge above.

Quick start

You can run rustfmt with Rust 1.24 and above.

On the Stable toolchain

To install:

rustup component add rustfmt

To run on a cargo project in the current working directory:

cargo fmt

On the Nightly toolchain

For the latest and greatest rustfmt, nightly is required.

To install:

rustup component add rustfmt --toolchain nightly

To run on a cargo project in the current working directory:

cargo +nightly fmt

Installing from source

To install from source (nightly required), first checkout to the tag or branch for the version of rustfmt you want.

The easiest way to install is via cargo make

cargo make install

Alternatively, you can run cargo install directly as long as you set the required environment variables and features.

export CFG_RELEASE=nightly
export CFG_RELEASE_CHANNEL=nightly
cargo install --path . --force --locked --features rustfmt,cargo-fmt

(Windows users can use set to specify the environment variable values)

This will install rustfmt in your ~/.cargo/bin. Make sure to add the ~/.cargo/bin directory to your PATH variable.

Usage

Please use rustfmt --help to see information about available arguments.

Running cargo fmt

The easiest way to run rustfmt against a project is with cargo fmt. cargo fmt works on both single-crate projects and cargo workspaces. Please see cargo fmt --help for usage information.

You can specify the path to your own rustfmt binary for cargo to use by setting theRUSTFMT environment variable. This was added in v1.4.22, so you must have this version or newer to leverage this feature (cargo fmt --version)

Running rustfmt directly

To format individual files or arbitrary codes from stdin, the rustfmt binary should be used. Some examples follow:

  • rustfmt lib.rs main.rs will format "lib.rs" and "main.rs" in place
  • rustfmt will read a code from stdin and write formatting to stdout
    • echo "fn main() {}" | rustfmt would emit "fn main() {}".

For more information, including arguments and emit options, see rustfmt --help.

Verifying code is formatted

When running with --check, Rustfmt will exit with 0 if Rustfmt would not make any formatting changes to the input, and 1 if Rustfmt would make changes.

Exit codes

In other modes, Rustfmt will exit with 1 if there was some error during formatting (for example a parsing or internal error) and 0 if formatting completed without error (whether or not changes were made).

Configuring Rustfmt

Rustfmt is designed to be very configurable. You can create a TOML file called rustfmt.toml or .rustfmt.toml, place it in the project or any other parent directory and it will apply the options in that file. See the config website for all available options.

By default, Rustfmt uses a style which conforms to the Rust style guide that has been formalized through the style RFC process.

Configuration options are either stable or unstable. Stable options can always be used on any channel. Unstable options are always available on nightly, but can only be used on stable and beta with an explicit opt-in (starting in Rustfmt v2.0).

Unstable options are not available on stable/beta with Rustfmt v1.x.

See the configuration documentation on the Rustfmt GitHub page for details (look for the unstable_features section).

Differences in rustfmt versions

Default formatting of submodules

On an invocation rustfmt lib.rs, rustfmt 1.x would format both "lib.rs" and any out-of-file submodules referenced in "lib.rs", unless the skip_children configuration option was true.

With rustfmt 2.x, this behavior requires the --recursive flag (#3587). By default, out-of-file submodules of given files are not formatted.

Note that this only applies to the rustfmt binary, and does not impact cargo fmt.

Construction of config options

Rustfmt 1.x uses only the configuration options declared in the rustfmt configuration file nearest the directory rustfmt is invoked.

Rustfmt 2.x merges configuration options from all configuration files in all parent directories, with configuration files nearer the current directory having priority.

Please see Configurations for more information and #3881 for the motivating issue.

Rust's Editions

Rustfmt is able to pick up the edition used by reading the Cargo.toml file if executed through the Cargo's formatting tool cargo fmt. Otherwise, the edition needs to be specified in rustfmt.toml, e.g., with edition = "2018".

Limitations

Rustfmt tries to work on as much Rust code as possible. Sometimes, the code doesn't even need to compile! However, there are some things that Rustfmt can't do or can't do well. The following list enumerates such limitations:

  • A program where any part of the program does not parse (parsing is an early stage of compilation and in Rust includes macro expansion).
  • Any fragment of a program (i.e., stability guarantees only apply to whole programs, even where fragments of a program can be formatted today).
  • Bugs in Rustfmt (like any software, Rustfmt has bugs, we do not consider bug fixes to break our stability guarantees).

Running Rustfmt from your editor

Checking style on a CI server

To keep your code base consistently formatted, it can be helpful to fail the CI build when a pull request contains unformatted code. Using --check instructs rustfmt to exit with an error code if the input is not formatted correctly. It will also print any found differences. (Older versions of Rustfmt don't support --check, use --write-mode diff).

A minimal Travis setup could look like this (requires Rust 1.31.0 or greater):

language: rust
before_script:
- rustup component add rustfmt
script:
- cargo build
- cargo test
- cargo fmt -- --check

See this blog post for more info.

How to build and test

We recommend using cargo make when working with the rustfmt codebase.

You can alternatively use cargo directly, but you'll have to set the CFG_RELEASE and CFG_RELEASE_CHANNEL environment variables and also provide the corresponding features.

For example:

export CFG_RELEASE=1.45.0-nightly
export CFG_RELEASE_CHANNEL=nightly

(Windows users can use set to specify the environment variable values)

To build with cargo make:

cargo make build

Or alternatively with cargo directly:

cargo build --all-features
# or
CFG_RELEASE_CHANNEL=nightly CFG_RELEASE=1.45.0-nightly cargo build --all-features

To run tests with cargo make:

cargo make test

Or alternatively with cargo directly:

cargo test --all-features
# or
CFG_RELEASE_CHANNEL=nightly CFG_RELEASE=1.45.0-nightly cargo test --all-features

To run rustfmt after this, use cargo run --bin rustfmt -- filename. See the notes above on running rustfmt.

Tips

  • For things you do not want rustfmt to mangle, use #[rustfmt::skip]

  • To prevent rustfmt from formatting a macro or an attribute, use #[rustfmt::skip::macros(target_macro_name)] or #[rustfmt::skip::attributes(target_attribute_name)]

    Example:

    #![rustfmt::skip::attributes(custom_attribute)]
    
    #[custom_attribute(formatting , here , should , be , Skipped)]
    #[rustfmt::skip::macros(html)]
    fn main() {
        let macro_result1 = html! { <div>
    Hello</div>
        }.to_string();
  • When you run rustfmt, place a file named rustfmt.toml or .rustfmt.toml in target file directory or its parents to override the default settings of rustfmt. You can generate a file containing the default configuration with rustfmt --print-config default rustfmt.toml and customize as needed.

  • After successful compilation, a rustfmt executable can be found in the target directory.

  • If you're having issues compiling Rustfmt (or compile errors when trying to install), make sure you have the most recent version of Rust installed.

  • You can change the way rustfmt emits the changes with the --emit flag:

    Example:

    cargo fmt -- --emit files

    Options:

    Flag Description Nightly Only
    files overwrites output to files No
    stdout writes output to stdout No
    checkstyle emits in a checkstyle format Yes
    json emits diffs in a json format Yes

License

Rustfmt is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT for details.

Comments
  • Fixed #215

    Fixed #215

    The code is a hack. That is the best way of putting it, but it works.

    I did think of maybe re-writing how WriteMode works as it seems, to me at lest, that not all the features are implemented/documented. That or I might have understood all of it, I'm pretty new at Rust.

    opened by svmnotn 33
  • Add project-specific configuration file support.

    Add project-specific configuration file support.

    It's now possible to create a file relative to a project that will override the default values. That file is called "rustfmt.toml". The default values are stored in a file called "default.toml" and are expected to be in the same folder as the binary, regardless of where the binary is stored.

    A "default.toml" is still written next to the manifest because the test suite needs it.

    opened by sbstp 27
  • cargo fmt --all is slow in a workspace project

    cargo fmt --all is slow in a workspace project

    Problem cargo fmt --all runs unexpectedly slow in a medium-sized workspace project.

    Steps

    1. Run a GitHub workflow that runs cargo fmt --all on the repository.
    2. Check execution time.

    This run shows rustfmt and/or cargo pausing for more than 20 s before producing any output in verbose mode. Seen with timestamps in the raw log:

    2020-06-08T17:05:32.3268959Z [command]/usr/share/rust/.cargo/bin/cargo fmt --all --verbose -- --check --verbose
    2020-06-08T17:05:55.8733086Z [bench (2018)] "/home/runner/work/chain-libs/chain-libs/btree/benches/benchmark.rs"
    

    Notes

    Output of cargo version: cargo 1.44.0 (05d080faa 2020-05-06)

    Output of rustfmt --version rustfmt 1.4.14-stable (e417356 2020-04-21)

    Virtual environment information from GitHub workflow: Operating System Ubuntu 18.04.4 LTS Virtual Environment Environment: ubuntu-18.04 Version: 20200518.1 Included Software: https://github.com/actions/virtual-environments/blob/ubuntu18/20200518.1/images/linux/Ubuntu1804-README.md

    opened by mzabaluev 25
  • rustfmt fails with errors

    rustfmt fails with errors "left behind trailing whitespace"

    I have rustfmt-preview installed on the nightly toolchain (rustc 1.30.0-nightly (3edb355b7 2018-08-03)) using rustup.

    Runningcargo +nightly fmt on the crate: https://github.com/frankmcsherry/differential-dataflow results in numerous "left behind trailing whitespace" errors. Some sample errors:

    internal error: left behind trailing whitespace
      --> [..]/differential-dataflow/src/algorithms/prefix_sum.rs:70
       |
    70 |         .iterate(|ranges| 
       |                          ^
    warning: rustfmt may have failed to format. See previous 1 errors.
    
      --> [..]/differential-dataflow/examples/seb.rs:37
       |
    37 |       let cooccurrences = 
       |                          ^
      --> [..]/differential-dataflow/examples/seb.rs:44
       |
    44 |       let row_sums = 
       |                     ^
    
      --> [..]/differential-dataflow/examples/dataflow.rs:35
       |
    35 |             let (tweet_input, tweets) = scope.new_collection(); 
       |                                                                ^
    
    bug a-comments 
    opened by sdht0 25
  • Unclear error message: Rustfmt failed … line exceeded maximum length (sorry)

    Unclear error message: Rustfmt failed … line exceeded maximum length (sorry)

    This error message doesn't tell me what are the consequences, and what can I do to avoid the problem.

    Does "Rustfmt failed" mean the file could not be parsed and has not been formatted at all, or did it just skip that one line?

    Is that a bug/limitation of rustfmt, or a lint telling me to format code better?

    What's the maximum length? Can I configure it?

    I've got these errors pointing to a few lines that only contain comments, and are 100-109 characters long. I'm confused, because it doesn't seem like an excessive line length that could cause a tool to fail.

    opened by kornelski 25
  • rustfmt should avoid rightwards drifting big blocks of code

    rustfmt should avoid rightwards drifting big blocks of code

    Currently rustfmt formats from

                let mut arms = variants.iter().enumerate().map(|(i, &(ident, v_span, ref summary))| {
                    let i_expr = cx.expr_usize(v_span, i);
                    let pat = cx.pat_lit(v_span, i_expr);
    
                    let path = cx.path(v_span, vec![substr.type_ident, ident]);
                    let thing = rand_thing(cx, v_span, path, summary, |cx, sp| rand_call(cx, sp));
                    cx.arm(v_span, vec!( pat ), thing)
                }).collect::<Vec<ast::Arm> >();
    

    to

                let mut arms = variants.iter()
                                       .enumerate()
                                       .map(|(i, &(ident, v_span, ref summary))| {
                                           let i_expr = cx.expr_usize(v_span, i);
                                           let pat = cx.pat_lit(v_span, i_expr);
    
                                           let path = cx.path(v_span, vec![substr.type_ident, ident]);
                                           let thing = rand_thing(cx,
                                                                  v_span,
                                                                  path,
                                                                  summary,
                                                                  |cx, sp| rand_call(cx, sp));
                                           cx.arm(v_span, vec!(pat), thing)
                                       })
                                       .collect::<Vec<ast::Arm>>();
    

    which is much worse than the original.

    poor-formatting p-high 
    opened by nagisa 25
  • Fix exponential execution time by memoizing format_expr

    Fix exponential execution time by memoizing format_expr

    fix #4476 fix #4867 fix #5128

    The problem in those issues is, when max_width is tight, rustfmt should check all possible formattings, which is exponential relative to input size. By memoization of format_expr function, worst case execution time becomes O(n*max_width^3). I tried codes in those issues and it completed in a fraction of second.

    opened by HKalbasi 24
  • Imports reordering

    Imports reordering

    Fix for issue #3943. The root cause of the issue is that ::Foo from use ::Foo is represented by UseSegment::List as one item vector [::Foo]. However, in case of use ::{Foo}, after removing the {} the representation was two items vector [, Foo]. That caused the wrong sorting, as, for example cmp() considers [, Foo] as greater then [::foo]

    The fix assumes that the one item vector [::Foo] is the right representation.

    opened by davidBar-On 23
  • Add option space_before_fn_sig_paren

    Add option space_before_fn_sig_paren

    This option adds very little code, so it would be great to have it supported.

    It's an enum, because the tracking issue originally asked for a space before generics too, which is not part of this PR. This option can be extended later to add BeforeGenerics or AroundGenerics as other values. https://github.com/rust-lang/rustfmt/pull/4302#discussion_r448549821

    Tracking issue: #3564

    backport-triage 
    opened by dylni 23
  • Option to preserve indent in empty lines.

    Option to preserve indent in empty lines.

    Hello, it would be nice to have the option to put whitespace on empty lines to match the current indent level.

    fn foo() {
       let thing = 1;
       <- Keep this indent.
       let thing = 2;
    }
    
    opened by kevincox 23
  • Stabilize the `ignore` configuration

    Stabilize the `ignore` configuration

    This one does not affect how the code is formatted but allows specific files or directories to be excluded from formatting.

    What is needed for stabilizing this for one of the next releases?

    stabilisation-request 
    opened by sdroege 22
  • In documentation, hide about section when searching

    In documentation, hide about section when searching

    This commit hides the about section when the search bar is not empty, making it more discoverable to users that search is indeed working and they should look in the options section.

    opened by krtab 0
  • [Feature request] Vertical formatting for attributes

    [Feature request] Vertical formatting for attributes

    Hi, it would be really cool if an attribute's content could be arranged in more ways. (Similar to array_width)

    Example:

    Currently, if you have this attribute:

    #[diagnostic(
        code(...),
        url(...),
        severity(...)
    )]
    fn x() {...}
    

    It will get rearranged to:

    #[diagnostic(code(...), url(...), severity(...))]
    fn x() {...}
    

    It would be useful if there was an option specifically for vertical formatting in attributes' content

    feature-request blocked 
    opened by blyxyas 1
  • NOT token (!) inside a macro call inside `macro_rules!` erroneously de-indented (non-idempotency)

    NOT token (!) inside a macro call inside `macro_rules!` erroneously de-indented (non-idempotency)

    Minimal reproducer:

    mod ok {
        mod ok {
            const _: &'static str = stringify!(Foo: !Bar);
        }
    }
    
    macro_rules! ok_2 {
        () => {
            const _: i32 = !1;
        };
    }
    ok_2!();
    
    macro_rules! fail_dedented {
        () => {
            const _: &'static str = stringify!(Foo: !Bar);
        };
    }
    fail_dedented!();
    
    macro_rules! fail_dedented_nonidempotent {
        () => {
            const _: () = assert!(stringify!(Foo: !Bar).len() > 0, concat!(stringify!(Foo: !Bar), "Lorem ipsum dolor sit amet, consectetur adipiscing elit"));
        };
    }
    fail_dedented_nonidempotent!();
    
    macro_rules! fail_dedented_nonidempotent_2 {
        () => {
            const _: () = assert!(stringify!(Foo: !Bar).len() > 0, concat!(stringify!(Foo: !Bar), "Lorem ipsum dolor sit amet, consectetur adipiscing elit"));
        };
    }
    
    fail_dedented_nonidempotent_2!();
    

    formats to

    mod ok {
        mod ok {
            const _: &'static str = stringify!(Foo: !Bar);
        }
    }
    
    macro_rules! ok_2 {
        () => {
            const _: i32 = !1;
        };
    }
    ok_2!();
    
    macro_rules! fail_dedented {
        () => {
    const _: &'static str = stringify!(Foo: !Bar);
        };
    }
    fail_dedented!();
    
    macro_rules! fail_dedented_nonidempotent {
        () => {
    const _: () = assert!(
                stringify!(Foo: !Bar).len() > 0,
                concat!(
                    stringify!(Foo: !Bar),
                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
                )
            );
        };
    }
    fail_dedented_nonidempotent!();
    
    macro_rules! fail_dedented_nonidempotent_2 {
        () => {
    const _: () = assert!(
                stringify!(Foo: !Bar).len() > 0,
                concat!(
                    stringify!(Foo: !Bar),
                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
                )
            );
        };
    }
    
    fail_dedented_nonidempotent_2!();
    

    formats to

    mod ok {
        mod ok {
            const _: &'static str = stringify!(Foo: !Bar);
        }
    }
    
    macro_rules! ok_2 {
        () => {
            const _: i32 = !1;
        };
    }
    ok_2!();
    
    macro_rules! fail_dedented {
        () => {
    const _: &'static str = stringify!(Foo: !Bar);
        };
    }
    fail_dedented!();
    
    macro_rules! fail_dedented_nonidempotent {
        () => {
            const _: () = assert!(
        stringify!(Foo: !Bar).len() > 0,
                concat!(
            stringify!(Foo: !Bar),
                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
                )
            );
        };
    }
    fail_dedented_nonidempotent!();
    
    macro_rules! fail_dedented_nonidempotent_2 {
        () => {
            const _: () = assert!(
        stringify!(Foo: !Bar).len() > 0,
                concat!(
            stringify!(Foo: !Bar),
                    "Lorem ipsum dolor sit amet, consectetur adipiscing elit"
                )
            );
        };
    }
    
    fail_dedented_nonidempotent_2!();
    
    bug a-macros 
    opened by jinohkang-theori 2
  • Don't remove non-breaking space in block comment with bare lines

    Don't remove non-breaking space in block comment with bare lines

    Fixes #5638

    Block comments with bare lines are those that have lines without leading * characters. When reformatting these comments we should be mindful not to remove leading non-breaking spaces (U+00A0).

    pr-not-reviewed 
    opened by ytmimi 0
  • Preserve markdown's double-space line break syntax in block doc comment

    Preserve markdown's double-space line break syntax in block doc comment

    Fixes #5639

    Now we'll preserve two blank lines at the end of block doc comments that contain bare lines (lines without a leading *).

    For example, the newlines in the following block doc comment won't be removed.

    /*!
    This  
    has  
    breaks.
    */
    
    pr-not-reviewed 
    opened by ytmimi 0
Releases(v1.5.1)
Owner
The Rust Programming Language
The Rust Programming Language
compile rust code into memes

cargo-memex Besides their size, rust binaries have a significant disadvantage: rust binaries are not memes yet. cargo-memex is a cargo subcommand that

Matthias Seitz 243 Dec 11, 2022
Create evolving artistic images with hot-code-reloaded Lisp and GLSL.

Shadergarden is a tool for building hot-code-reloadable shader pipelines. For a tutorial for how to get started, consult the introductory

Tonari, Inc 101 Dec 29, 2022
Detects usage of unsafe Rust in a Rust crate and its dependencies.

cargo-geiger ☢️ A program that lists statistics related to the usage of unsafe Rust code in a Rust crate and all its dependencies. This cargo plugin w

Rust Secure Code Working Group 1.1k Dec 26, 2022
Powerful database anonymizer with flexible rules. Written in Rust.

[Data]nymizer Powerful database anonymizer with flexible rules. Written in Rust. Datanymizer is created & supported by Evrone. What else we develop wi

[Data]nymizer 381 Dec 26, 2022
⚡️Lightning-fast linter for .env files. Written in Rust 🦀

⚡️ Lightning-fast linter for .env files. Written in Rust ?? Dotenv-linter can check / fix / compare .env files for problems that may cause the applica

null 1.5k Jan 9, 2023
The Rust toolchain installer

rustup: the Rust toolchain installer Master CI Build Status Windows macOS Linux Etc rustup installs The Rust Programming Language from the official re

The Rust Programming Language 5.1k Jan 8, 2023
Repository for the Rust Language Server (aka RLS)

Rust Language Server (RLS) The RLS provides a server that runs in the background, providing IDEs, editors, and other tools with information about Rust

The Rust Programming Language 3.6k Jan 7, 2023
🦀 The ultimate search extension for Rust

Rust Search Extension 简体中文 The ultimate search extension for Rust Search docs, crates, builtin attributes, official books, and error codes, etc in you

Huhu 962 Dec 30, 2022
a freeform Rust build system

tinyrick: a freeform Rust build system .---. ^ o{__ω__ o{ ^0^ -Let me out! ~~ ( // *|* \xx\) xx`|' = =

Andrew 48 Dec 16, 2022
The Curly programming language (now in Rust!)

Curly Curly is a functional programming language that focuses on iterators. Some of its main implementation features include sum types, iterators, lis

Curly Language 30 Jan 6, 2023
Some WIP payload in Rust running on M1.

m1saka Some WIP payload in Rust running on M1. Project informations The aim of this payload is to provide exploration capabilities while providing a s

Mary 10 Mar 7, 2021
A library to compile USDT probes into a Rust library

sonde sonde is a library to compile USDT probes into a Rust library, and to generate a friendly Rust idiomatic API around it. Userland Statically Defi

Wasmer 39 Oct 12, 2022
⚙️ Workshop Publishing Utility for Garry's Mod, written in Rust & Svelte and powered by Tauri

⚙️ gmpublisher Currently in Beta development. A powerful and feature-packed Workshop publisher for Garry's Mod is finally here! Click for downloads Ar

William 484 Jan 7, 2023
A neofetch alike program that shows hardware and distro information written in rust.

nyafetch A neofetch alike program that shows hardware and distro information written in rust. installing install $ make install # by default, install

null 16 Dec 15, 2022
Automated license checking for rust. cargo lichking is a Cargo subcommand that checks licensing information for dependencies.

cargo-lichking Automated license checking for rust. cargo lichking is a Cargo subcommand that checks licensing information for dependencies. Liches ar

Nemo157 120 Dec 19, 2022
Create target folder as a RAMdisk for faster Rust compilation.

cargo-ramdisk This crate is only supported for unix like systems! cargo-ramdisk creates a ramdisk at the target folder of your project for ridiculousl

PauMAVA 20 Jan 8, 2023
cargo extension that can generate BitBake recipes utilizing the classes from meta-rust

cargo-bitbake cargo bitbake is a Cargo subcommand that generates a BitBake recipe that uses meta-rust to build a Cargo based project for Yocto Install

null 60 Oct 28, 2022
A small utility to compare Rust micro-benchmarks.

cargo benchcmp A small utility for comparing micro-benchmarks produced by cargo bench. The utility takes as input two sets of micro-benchmarks (one "o

Andrew Gallant 304 Dec 27, 2022
"goto" implementation for Rust

Goto/Label for Rust Tired of using newfangled control flow mechnisms like "loop," "while," and "for"? Well worry no more! Finally, "goto" and "label"

Dagan Martinez 92 Nov 9, 2022