#5804·dioxus

`dx fmt` grows indentation of multi-line raw string literals inside deeply nested closures on every run (non-idempotent)

Author: DicklessgreatCreated Sep 2, 2026Updated Sep 2, 2026
Labelsbug

Bug description

dx fmt is not idempotent when a multi-line raw string literal (r#"..."#) appears inside a deeply nested block (e.g. a closure passed to spawn, inside a match arm, inside an rsx! element handler). Running dx fmt repeatedly on an already-formatted file keeps increasing the indentation of the string's content on every single run, instead of converging to a stable output. Since the content between the raw string's newlines is real string data (this pattern is commonly used to build up a JS snippet passed to document::eval), this also silently corrupts the string's value, not just its on-screen indentation.

We noticed this because our team's Claude Code PostToolUse hook runs dx fmt -f <file> after every edit. Over many edits to the same file, one particular raw-string literal grew to 1000+ characters of leading whitespace before we noticed.

Steps to reproduce

  1. Save the file below as repro.rs (no Cargo project needed — reproduces even with a bare dx fmt -f).
  2. Run dx fmt -f repro.rs three times in a row, diffing after each run.
rust
use dioxus::prelude::*;

#[component]
fn App() -> Element {
    rsx! {
        div {
            for _ in 0..1 {
                button {
                    onclick: move |_evt| {
                        spawn(async move {
                            match Ok::<(), ()>(()) {
                                Ok(()) => {
                                    let script = format!(
                                        r#"
                                        requestAnimationFrame(() => {{
                                            console.log("restore");
                                        }});
                                        "#
                                    );
                                    let _ = script;
                                }
                                Err(_) => {}
                            }
                        });
                    },
                    "click"
                }
            }
        }
    }
}

Actual behavior

The indentation of the raw string's body grows on every single run (measured as line length in characters, including leading whitespace):

requestAnimationFrame(() => {{ line length console.log(...) line length
run 1 86 83
run 2 102 99
run 3 118 115

(+16 characters per run, unbounded — it never converges.)

Expected behavior

dx fmt should be idempotent: formatting an already-formatted file should produce no diff. At minimum, it should not keep growing indentation without bound across repeated runs.

Environment

  • dx --version: dioxus 0.7.10 (57d6794)
  • rustc --version: rustc 1.95.0
  • OS: Linux x86_64

Additional notes

We also observed a related (but distinct) non-idempotency bug in 0.7.5 involving multi-line continuations of a comparison inside an rsx! attribute value (e.g. checked: some_call()\n== Other::Variant,), which appears to have been fixed between 0.7.5 and 0.7.10. The raw-string case above is still present in 0.7.10.

As a workaround, we refactored the affected code to extract the raw string literal into a shallowly-nested top-level function instead of inlining it inside the deeply nested closure, which avoids triggering the bug.