構文の予約

概要

  • shikibetsushi#, shikibetsushi"...", shikibetsushi'...' の3つの構文が新たに予約され、トークン分割されなくなりました。
  • 主に影響を受けるのはマクロです。例えば、quote!{ #a#b } と書くことはできなくなりました。
  • キーワードが特別扱いされることもないので、例えば match"..." {} と書くこともできなくなりました。
  • 識別子と後続の #, ", ' の間に空白文字を挿入することで、エラーを回避できます。
  • エディション移行ツールは、必要な場所に空白を挿入してくれます。

詳細

私達は、将来新しい構文を導入する余地を残すため、接頭辞付きの識別子とリテラルの構文を予約することにしました。 予約されたのは、任意の識別子 prefix を用いて prefix#identifier, prefix"string", prefix'c', prefix#123 のいずれかの形で書かれるものです。 (ただし、b'...'(バイト文字列)やr"..."(生文字列)のように、すでに意味が割り当てられているものを除きます。)

これにより、将来エディションをまたくごとなく構文を拡張できるようになります。 これを、次のエディションまでの一時的な構文のために使ったり、もし適切なら、恒久的な構文のために使ったりするでしょう。

エディションの区切りがないと、これは破壊的変更に当たります。 なぜなら、現在のマクロは、例えば hello"world" という構文を、 hello"world" の2つのトークンとして受け入れるからです。 もっとも、(自動)修正はシンプルで、hello "world" のように空白を入れるだけです。 同様に、prefix#identprefix #ident とする必要があります。 エディション移行ツールは、そのように修正してくれます。

これが提案された RFC は、このような書き方をトークン分割エラーにすると決めているだけで、 特定の接頭辞に意味を持たせることはまだしていません。 接頭辞に何らかの役割を割り当てるのは、将来の提案にその余地が残されています。 接頭辞が予約されたおかげで、今後は破壊的変更なく新しい構文を導入できます。

例えば、以下のような接頭辞が使えるようになるかもしれません(ただし、いずれもまだ提案が固まったわけではありません):

  • k#keyword で、現在のエディションにまだ導入されていないキーワードを書けるようにする。 たとえば、2015 エディションでは async はキーワードではありませんが、 このような接頭辞が使えたのならば、2018 エディションで async が予約語になるのを待たずに、2015 エディションでも k#async が使えたということになります。
  • f"" で、フォーマット文字列の略記とする。 例えば、f"hello {name}" と書いたら、それと等価な format!() の呼び出しと見なす。
  • s""String リテラルを表す。
  • c""z"" で、ヌル終端のC言語の文字列を表す。

移行

Rust 2018 のコードベースから Rust 2021 への自動移行の支援のため、2021 エディションには、移行用のリントrust_2021_prefixes_incompatible_syntax が追加されています。

rustfix でコードを Rust 2021 エディションに適合させるためには、次のように実行します。

cargo fix --edition

コード移行を手で行いたいか、行う必要があっても、移行は非常に簡単です。

例えば、次のように定義されたマクロがあったとしましょう:


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

Rust 2015 と 2018 では、以下のように、1つ目と2つ目のトークンの間に空白を入れることなくマクロを呼び出しても問題ありませんでした:

my_macro!(z"hey");

Rust 2021 では z という接頭辞は許されないので、このマクロを呼び出すためには、以下のように接頭辞の後にスペースを入れる必要があります:

my_macro!(z "hey");