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)] }