Strings and Text Processing

format!

The format! macro interpolates values using std::fmt formatting rules and returns a newly allocated String without printing to standard output.

Basic Usage and Inline Variable Capture

Starting in Rust 1.58 (and standard in the 2024 edition), format! captures local variables directly by name inside {var} placeholders, while more complex expressions ({a + b}, {user.name}) are passed as positional or named arguments after the format string:

fn main() {
    let host = "db.internal";
    let port = 5432_u16;
    let tls = true;

    // Captures `host` and `port` directly from scope; evaluates expression as positional arg:
    let dsn = format!(
        "postgres://{host}:{port}/app?sslmode={}",
        if tls { "require" } else { "disable" }
    );

    println!("{dsn}");
}
postgres://db.internal:5432/app?sslmode=require

Non-Consuming Reference Semantics of format!

Unlike the + operator on String (a + &b, which moves and consumes a), format! borrows all of its arguments by shared reference (&T). Every variable passed to format! remains valid and owned by the caller afterward:

fn main() {
    let first = String::from("Rust");
    let second = String::from("2024");

    let combined = format!("{first} {second} Edition");

    // Both `first` and `second` are still valid:
    println!("Combined: '{combined}' (from '{first}' and '{second}')");
}
Combined: 'Rust 2024 Edition' (from 'Rust' and '2024')

Compile-Time Type Checking (E0277)

format! parses the format string at compile time using format_args! and verifies that every interpolated argument implements the requested formatting trait (Display for {}, Debug for {:?}, LowerHex for {:x}). Referencing a type that does not implement Display with {} fails at compile time with E0277:

// ❌ does not compile
struct Point {
    x: i32,
    y: i32,
}

fn main() {
    let p = Point { x: 1, y: 2 };
    let s = format!("{p}");
}
error[E0277]: `Point` doesn't implement `std::fmt::Display`
 --> src/main.rs:9:22
  |
9 |     let s = format!("{p}");
  |                      ^^^ `Point` cannot be formatted with the default formatter
  |
  = help: the trait `std::fmt::Display` is not implemented for `Point`
  = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead

Appending Formatted Text to an Existing String with write!

Calling s.push_str(&format!(...)) allocates a temporary String only to copy its bytes into s and drop the temporary. Instead, import std::fmt::Write and use write!(&mut s, ...) to format directly into s's existing buffer with zero temporary allocations:

use std::fmt::Write;

fn main() {
    let mut query = String::from("SELECT * FROM items WHERE id IN (");

    for (i, id) in [10, 20, 30].iter().enumerate() {
        if i > 0 {
            query.push_str(", ");
        }
        write!(&mut query, "{id}").unwrap();
    }
    query.push(')');

    println!("{query}");
}
SELECT * FROM items WHERE id IN (10, 20, 30)