I find these technical arguments important, because I'd rather we not complicate the already-complex parser any more – please, please consider not making the mental model for, and the life of, proc-macro authors harder! It's also ugly and just doesn't feel right to intertwingle something so simple and fundamental from the core language as a string literal with something much higher-level from library-land as arbitrary expressions formatting. Incidentally, I wonder if it would require making
Display and the other half dozen formatting traits into lang items, which would be highly undesirable.
However, I'll still jump in here with a non-technical argument against allowing arbitrary expressions: it's plain old harder to read. People do this all the time in Swift and it gives me the shivers to read a "string literal" that in turn contains 10 nested subexpressions, 20 unexpected side effects, 30 decrypted nuclear launch codes and 40 kitten corpses.
Moreover, my perception is that it's not only those kind of overly complex expressions (which could reasonably be linted away); even simple stuff gets ugly quickly when e.g. it contains embedded parentheses for function calls or array indexing.
I think allowing the single-identifier case only hits a sweet spot between convenience of writing and reading. Furthermore, we have precedent in Rust for inferring a single variable name from context but disallowing an unnamed expression: namely, in
struct initializers. There we can also leave off the redundant
foo: foo part if the field and the initializing variable have identical names, but otherwise the field must be named explicitly. I do realize that's a somewhat different situation and there's a different reason, but it's still a parallel.