Reserved syntax

Summary

  • Unprefixed guarded strings of the form #"foo"# are reserved for future use.
  • Two or more # characters are reserved for future use.

Details

RFC 3593 reserved syntax in the 2024 Edition for guarded string literals that do not have a prefix to make room for possible future language changes. The 2021 Edition reserved syntax for guarded strings with a prefix, such as ident##"foo"##. The 2024 Edition extends that to also reserve strings without the ident prefix.

There are two reserved syntaxes:

  • One or more # characters immediately followed by a string literal.
  • Two or more # characters in a row (not separated by whitespace).

This reservation is done across an edition boundary because of interactions with tokenization and macros. For example, consider this macro:

#![allow(unused)] fn main() { macro_rules! demo { ( $a:tt ) => { println!("one token") }; ( $a:tt $b:tt $c:tt ) => { println!("three tokens") }; } demo!("foo"); demo!(r#"foo"#); demo!(#"foo"#); demo!(###) }

Prior to the 2024 Edition, this produces:

one token one token three tokens three tokens

Starting in the 2024 Edition, the #"foo"# line and the ### line now generates a compile error because those forms are now reserved.

Migration

The rust_2024_guarded_string_incompatible_syntax lint will identify any tokens that match the reserved syntax, and will suggest a modification to insert spaces where necessary to ensure the tokens continue to be parsed separately.

The lint is part of the rust-2024-compatibility lint group which is included in the automatic edition migration. In order to migrate your code to be Rust 2024 Edition compatible, run:

cargo fix --edition

Alternatively, you can manually enable the lint to find macro calls where you may need to update the tokens:

#![allow(unused)] fn main() { // Add this to the root of your crate to do a manual migration. #![warn(rust_2024_guarded_string_incompatible_syntax)] }