Skip to content

Formatting as macros

print!, println!, eprint!, eprintln!, format! and panic! are the compiler’s own macros, as the intrinsics are, chosen by the user once M10 had landed: invoked println!(…) like an expr macro, since they read like a call (18.9; r64 had spelled them #println). format! replaces String::format and takes allocator = … by name. Any Format is an argument, a type’s own included, so printing a Vec2 no longer goes through a String; an enum, an optional and a pointer have none. Their names are reserved; a bare println(…) is an unknown name whose help says to write println!. Arguments are evaluated as a call’s are — all before anything is written, temporaries living until the text is — because the invocation lowers to one call: the text between placeholders and each spec, split at compile time, and the arguments as &Format, written in turn by std’s Formatter, straight to the stream with no intermediate String. Lowering to one statically-dispatched Format::format call per placeholder was tried and dropped: a sequence of statements ends each argument’s temporaries before the line is written, which a call does not. panic! formats without allocating, since the allocators panic too. error(…) stays a function: #error is a macro’s own rejection (§12.6), and an Error’s message keeps its static storage (§9.2) (§12.9)

Amended in r69 (T-0056, D-0082). An invocation no longer lowers to one call taking &Format: its arguments are evaluated and kept as a call’s are — so what their evaluation made still lives until the text is written — and then each placeholder is written by a direct call to its argument’s Format::format, the statically-dispatched shape dropped above, now without ending temporaries early. And a pointer is written as what it points at, its address by {:p} (D-0082), where this said a pointer has no Format.