保留语法

摘要

  • any_identifier#any_identifier"..."any_identifier'...' 现在是保留语法,不再进行词法分析。
  • 这主要与宏相关。例如,quote!{ #a#b } 不再被接受。
  • 它不会特殊对待关键字,因此例如 match"..." {} 也不再被接受。
  • 在标识符和后续的 #"' 之间插入空格以避免错误。
  • 版本迁移将帮助您在这些情况下插入空格。

详情

为了给将来的新语法腾出空间,我们决定为带前缀的标识符和字面量保留语法:prefix#identifierprefix"string"prefix'c'prefix#123,其中 prefix 可以是任何标识符。(除了那些已经有含义的前缀,例如 b'...'(字节字符)和 r"..."(原始字符串)。)

这提供了我们将来可以扩展到的语法,而不需要版本边界。我们可以将此语法用于下一个版本之前的临时语法,或者在适当的情况下用于永久语法。

如果没有版本,这将是一个破坏性更改,因为宏当前可以接受 hello"world" 等语法,它们会将其视为两个独立的标记:hello"world"。不过,修复方法很简单(自动):只需插入一个空格:hello "world"。同样,prefix#ident 应该变为 prefix #ident。版本迁移将帮助您完成此修复。

除了将这些转换为词法分析错误之外,RFC 尚未为任何前缀附加含义。将含义分配给特定前缀的工作留给未来的提案,由于保留了这些前缀,这些提案现在不会再是破坏性更改。

您将来可能会看到的一些新前缀(尽管我们尚未承诺其中任何一个)

  • k#keyword 允许编写当前版本中尚不存在的关键字。例如,虽然 async 在 2015 版中不是关键字,但此前缀将允许我们在 2015 版中接受 k#async,而无需等到 2018 版将 async 保留为关键字。

  • f"" 作为格式字符串的简写。例如,f"hello {name}" 是等效 format!() 调用的简写。

  • s"" 用于 String 字面量。

迁移

作为 2021 版的一部分,添加了迁移 lint rust_2021_prefixes_incompatible_syntax,以帮助将 Rust 2018 代码库自动迁移到 Rust 2021。

要将代码迁移为与 Rust 2021 版兼容,请运行

cargo fix --edition

如果您想要或需要手动迁移代码,则迁移过程相当简单。

假设您有一个像这样定义的宏

#![allow(unused)]
fn main() {
macro_rules! my_macro {
    ($a:tt $b:tt) => {};
}
}

在 Rust 2015 和 2018 中,允许在第一个标记树和第二个标记树之间没有空格的情况下调用此宏,如下所示

my_macro!(z"hey");

z 前缀在 Rust 2021 中不再允许,因此要调用此宏,您必须在前缀后添加一个空格,如下所示

my_macro!(z "hey");