Skip to content

f-strings everywhere: only f"..." interpolates, messages included - #116

Merged
Kinflou merged 1 commit into
masterfrom
feat/f-string-messages
Oct 18, 2026
Merged

Kinflou merged 1 commit into
masterfrom
feat/f-string-messages

Conversation

@Kinflou

@Kinflou Kinflou commented Oct 18, 2026

Copy link
Copy Markdown
Member

Interpolation had two spellings. A constant needed f"page {N}", but an error's message and an assert's message interpolated in a plain "…", and f"…" there was a parse error. Now the rule is the same everywhere: only an f-string interpolates.

Grammar. A message (message = …, and an assert's second argument) is "…", printed as written, or f"…", with {path} placeholders and {{/}} escapes as for a constant. Both carry their span.

IR

  • The template now keeps {{/}} escapes, and every brace in a plain message comes out escaped. A reader can always tell a literal brace from a placeholder. Before, reconstruct collapsed escapes into bare braces, the ambiguity comline-rust's message renderer worked around. Templates without literal braces are unchanged.
  • New fields, all serde(default):
    • Error.message_span and Error.uninterpolated;
    • Assert.message_span and Assert.uninterpolated;
    • Validator.validate_span.

Diagnostics

  • New warning validation::message-not-interpolated, the migration aid. A path written like a placeholder in a plain message, e.g. "{value.name} is empty", is printed as written. The warning sits on the message, and the help says to write f"…". A re-exported error is warned about only where it's declared.
  • validator-checks-nothing with an empty validate block now points at the block and names the validator as a secondary location. Without a block it says so, and its example is now an f-string.
  • The unused-property check reads placeholders with {{ skipped, so an escaped {{params.x}} doesn't count as a use.

Migration

  • std's StringBounds now uses f-strings.
  • Core's tests and fixtures that mean interpolation now use f"…"; expected IR templates are unchanged.
  • The error and message vocabulary entries are reworded.

Tests: escape round-trips for both kinds of string, plain braces parsing, the new warning and its spans, the validate-block span, and literal braces not counting as placeholders. The full suite passes.

Follow-ups:

  • comline-rust reads {{/}} in templates;
  • the language server adds a quick fix that adds the f, f-string highlighting, and a VS Code </> fix;
  • fixtures, docs and the cascade.

An error's message and an assert's message interpolated in a plain
"...", while a constant needed f"..." - two spellings for one idea,
and f"..." in a message was a parse error. Now a message is either:
"...", printed as written, or f"...", which interpolates, as a
constant's does.

The frozen template keeps {{ / }} escapes (a plain message's braces all
come out escaped), so a reader can always tell a literal brace from a
placeholder - reconstruct collapsed them before, the old ambiguity the
Rust generator worked around.

Migration help: a path written like a placeholder in a plain message,
"{value.name} is empty", is recorded and warned about at the message
(validation::message-not-interpolated). std's StringBounds is f-strings.

And a validator whose validate block is empty is warned about at that
block, naming the validator as a secondary location.
@Kinflou
Kinflou merged commit 0b1f4b7 into master Oct 18, 2026
9 checks passed
@Kinflou
Kinflou deleted the feat/f-string-messages branch October 18, 2026 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant