保留语法

概要

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

详情

为了在未来为新语法腾出空间,我们决定保留前缀标识符、字面量和生命周期的语法:prefix#identifierprefix"string"prefix'c'prefix#123'prefix#,其中 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");

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

my_macro!(z "hey");