Clippy lints / Pedantic
Clippy lint · Pedantic · checked with Clippy 0.1.99
clippy::format_collect: use of `format!` to build up a string from an iterator
What it meansChecks for usage of .map(|_| format!(..)).collect::<String>(). It is in the pedantic group and off by default.
What you see
warning: use of `format!` to build up a string from an iterator --> main.rs:4:5 | 4 | bytes.iter().map(|b| format!("{b:02X}")).collect() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: call `fold` instead --> main.rs:4:18 | 4 | bytes.iter().map(|b| format!("{b:02X}")).collect() | ^^^ help: ... and use the `write!` macro here --> main.rs:4:26 | 4 | bytes.iter().map(|b| format!("{b:02X}")).collect() | ^^^^^^^^^^^^^^^^^^ = note: this can be written more efficiently by appending to a `String` directly = help: for further information visit https://rust-lang.github.io/rust-clippy/stable/index.html#format_collect = note: `-W clippy::format-collect` implied by `-W clippy::pedantic`
Real output of Clippy 0.1.99 (Rust 1.99) on the example below. Names and line numbers in yours will differ.
Does it matter?
This allocates a new string for every element in the iterator. This can be done more efficiently by creating the String once and appending to it in Iterator::fold, using either the write! macro which supports exactly the same syntax as the format! macro, or concatenating with + in case the iterator yields &str/String. Note also that write!-ing into a String can never fail, despite the return type of write! being std::fmt::Result, so it can be safely ignored or unwrapped.
Stricter lints with some false positives. Off by default; opt in with clippy::pedantic.
How to fix it
Clippy does not fix this one automatically. Change the code by hand:
Flagged
fn hex_encode(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02X}")).collect()
}
Write this instead
use std::fmt::Write;
fn hex_encode(bytes: &[u8]) -> String {
bytes.iter().fold(String::new(), |mut output, b| {
let _ = write!(output, "{b:02X}");
output
})
}
Turn it off, or on
It is off by default. To use it, set it to warn or deny:
Whole crate (Cargo.toml)
[lints.clippy]
format_collect = "warn"In code
#![warn(clippy::format_collect)]One run
cargo clippy -- -W clippy::format-collectThe [lints] table needs Rust 1.74 or newer. In a workspace, put it under [workspace.lints.clippy] and add [lints] workspace = true to each member.
Clippy's own documentation
What it does
Checks for usage of .map(|_| format!(..)).collect::<String>().
Why is this bad?
This allocates a new string for every element in the iterator.
This can be done more efficiently by creating the String once and appending to it in Iterator::fold,
using either the write! macro which supports exactly the same syntax as the format! macro,
or concatenating with + in case the iterator yields &str/String.
Note also that write!-ing into a String can never fail, despite the return type of write! being std::fmt::Result,
so it can be safely ignored or unwrapped.
Example
fn hex_encode(bytes: &[u8]) -> String {
bytes.iter().map(|b| format!("{b:02X}")).collect()
}
Use instead:
use std::fmt::Write;
fn hex_encode(bytes: &[u8]) -> String {
bytes.iter().fold(String::new(), |mut output, b| {
let _ = write!(output, "{b:02X}");
output
})
}
From the Clippy lint list (0.1.99), part of the Rust project, MIT or Apache-2.0. Official entry.
Related lints
- too_many_linesChecks for functions with a large amount of lines
- missing_errors_docChecks the doc comments of publicly visible functions that return a Result type and warns if there is no # Errors section
- must_use_candidateChecks for public functions that have no #[must_use] attribute, but return something not already marked must-use, have no mutable arg and mutate no statics
- flat_map_optionused `flat_map` where `filter_map` could be used instead
- float_cmpstrict comparison of `f32` or `f64`
- fn_params_excessive_boolsChecks for excessive use of bools in function declarations
- format_push_string`format!(..)` appended to existing `String`
- if_not_elseChecks for usage of ! or != in an if condition with an else branch
- ignore_without_reasonChecks for ignored tests without messages
All 847 Clippy lints · Rust compiler errors · Cargo.toml checker
Up next
Related lintclippy::too_many_linesChecks for functions with a large amount of linesRead it next →Did this answer your question?