Skip to content

Commit 8aefa12

Browse files
committed
Add exception for when we can update the specifier
In certain cases we may be able to update the fragment specifier simultaneously with adding new syntax without any risk of changing the behavior of existing macros. Let's add a footnote about that possibility in the background section, and let's add a paragraph in the policy that speaks to that. Clearly, in cases where we can prevent divergence, that's what we would do. (Thanks to Josh Triplett for raising this point.)
1 parent 8e4cefe commit 8aefa12

File tree

1 file changed

+5
-1
lines changed

1 file changed

+5
-1
lines changed

text/3531-macro-fragment-policy.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ Each macro is composed of one or more *rules*. Each of these rules has a *match
1515

1616
Within a matcher, different parts of the input Rust syntax can be bound to metavariables using *[fragment specifiers][]*. These fragment specifiers define what Rust syntax will be matched and bound to each metavariable. For example, the `item` fragment specifier matches an [item][], `block` matches a [block expression][], `expr` matches an [expression][], and so on.
1717

18-
As we add new features to Rust, sometimes we change its syntax. This means that, even within an edition, the definition of what exactly constitutes an [expression][], e.g., can change. However, to avoid breaking macros in existing code covered by our stability guarantee, we do not update within an edition what code is matched by the relevant fragment specifier (e.g., `expr`). This *skew* or divergence between the language and the fragment specifiers creates problems over time, including that macros become unable to match newer Rust syntax without dropping down to lower-level specifiers such as `tt`.
18+
As we add new features to Rust, sometimes we change its syntax. This means that, even within an edition, the definition of what exactly constitutes an [expression][], e.g., can change. However, to avoid breaking macros in existing code covered by our stability guarantee, we often do not update within an edition what code is matched by the relevant fragment specifier (e.g., `expr`).[^no-update-exception] This *skew* or divergence between the language and the fragment specifiers creates problems over time, including that macros become unable to match newer Rust syntax without dropping down to lower-level specifiers such as `tt`.
1919

2020
Periodically, we need a way to bring the language and the fragment specifiers back into sync. This RFC defines a policy for how we do that.
2121

22+
[^no-update-exception]: In certain cases we may be able to update the fragment specifier simultaneously with adding new syntax as described in the [policy][].
23+
2224
["macros by example"]: https://doc.rust-lang.org/reference/macros-by-example.html
2325
[block expression]: https://doc.rust-lang.org/reference/expressions/block-expr.html
2426
[expression]: https://doc.rust-lang.org/reference/expressions.html
@@ -43,6 +45,8 @@ A new fragment specifier that preserves the old behavior *must* be made availabl
4345

4446
As specified above, we will add the new fragment specifier that preserves the old behavior to the current edition, the next edition, and to as many other editions as practical. Adding the new specifier to the current and next edition will be done to facilitate migration. Adding it to as many other editions as practical will be done in keeping with our policy of preferring [uniform behavior across editions][]. Sometimes, however, it may not be practical to add the specifier to some other edition. E.g., the behavior being preserved may include handling a token that is a keyword in only some editions. In these cases, we'll add the new fragment specifier only to those editions where it makes sense.
4547

48+
In cases where we're adding new syntax and updating the grammar to include that new syntax, if we can update the corresponding fragment specifier simultaneously to match the new grammar in such a way that we do not risk changing the behavior of existing macros (i.e., because the new syntax previously would have failed parsing), then we will do that so as to prevent or minimize divergence between the fragment specifier and the new grammar. If that entirely prevents divergence, then no further action will be needed. Otherwise, the policy defined in this RFC will be used to correct any remaining divergence in the next edition.
49+
4650
[uniform behavior across editions]: https://github.com/rust-lang/rfcs/blob/master/text/3085-edition-2021.md#uniform-behavior-across-editions
4751

4852
# Alternatives

0 commit comments

Comments
 (0)