Multi-line string literals in Rust
18 September, 2025
Writing multi-line strings in Rust is quite awkward:
let sql = "create table student(
id int primary key,
name text
)";
I like how it works in Zig, I think Zig’s multi-line string literal syntax is one of the best:
const sql =
\\ create table student(
\\ id int primary key,
\\ name text
\\ )
;
Comments in Zig use //
and make content until end of the line part of the comment. Same with multi-line string literals, \\
makes everything after it a part of the string.
Incredible consistency.
I’ve been missing this feature a lot in Rust. There are some solutions for this problem, like the indoc
crate:
let sql = indoc! ;
Or you can do it using one of the following alternatives:
let sql = "\
create table student(
id int primary key,
name text
)";
let sql = concat!;
let sql = "\
create table student(\n\
id int primary key,\n\
name text\n\
)\
";
But none of those are satsifying to me.
The biggest selling point of multi-line string literals is that they would be automatically formatted by rustfmt
to match the surrounding indentation.
But wait… apparently Rust already has multi-line string literals? It’s just as elegant as Zig’s, and I’ve never seen anyone use it!
let sql = multi!;
This works since /// foo
is just syntax sugar for #[doc = r"foo"]
.
What I really like about this is that I can take the expression multi!(...)
and copy-paste it wherever I feel like, and the indentation will be preserved!.
And the best part, it is totally customizeable! You can make a cool new format!
macro that makes use of that syntax:
;
}
let foo = multi_format!;
It won’t work with interpolated variables, though:
let age = 0;
let bob = multi_format!;
“there is no argument named
age
” did you intend to capture a variableage
from the surrounding scope? to avoid ambiguity,format_args!
cannot capture variables when the format string is expanded from a macro
That’s unfortunate, it takes away from the utility of a naive implementatio!
That’s why I made a procedural macro docstr!
, which turns documentation into strings at compile-time:
use docstr;
let hello_world: &'static str = docstr!;
assert_eq!
Expands to this:
format!