Skip to content

Commit 26ec2c3

Browse files
authored
Merge pull request #1764 from ehuss/edition-admonition
Add edition admonitions
2 parents e95ebdf + 05e9434 commit 26ec2c3

23 files changed

+122
-75
lines changed

docs/authoring.md

+8-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ When assigning rules to new paragraphs, or when modifying rule names, use the fo
9595
* If the rule is naming a specific Rust language construct (e.g. an attribute, standard library type/function, or keyword-introduced concept), use the construct as named in the language, appropriately case-adjusted (but do not replace `_`s with `-`s).
9696
* Other than Rust language concepts with `_`s in the name, use `-` characters to separate words within a "subrule".
9797
* Whenever possible, do not repeat previous components of the rule.
98-
* Edition differences admonitions should typically be named by the edition referenced directly by the rule. If multiple editions are named, use the one for which the behavior is defined by the admonition, and not by a previous paragraph.
98+
* Edition differences admonitions should typically be named by the edition where the behavior changed. You should be able to correspond the dates to the chapters in <https://doc.rust-lang.org/edition-guide/>.
9999
* Target specific admonitions should typically be named by the least specific target property to which they apply (e.g. if a rule affects all x86 CPUs, the rule name should include `x86` rather than separately listing `i586`, `i686` and `x86_64`, and if a rule applies to all ELF platforms, it should be named `elf` rather than listing every ELF OS).
100100
* Use an appropriately descriptive, but short, name if the language does not provide one.
101101

@@ -197,4 +197,10 @@ The reference does not document which targets exist, or the properties of specif
197197

198198
### Editions
199199

200-
The main text and flow should document only the current edition. Whenever there is a difference between editions, the differences should be called out with an "Edition differences" block.
200+
The main text and flow should document only the current edition. Whenever there is a difference between editions, the differences should be called out with an edition block, such as:
201+
202+
```markdown
203+
r[foo.bar.edition2021]
204+
> [!EDITION-2021]
205+
> Describe what changed in 2021.
206+
```

mdbook-spec/src/lib.rs

+12
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,18 @@ impl Spec {
155155
let blockquote = &caps["blockquote"];
156156
let initial_spaces = blockquote.chars().position(|ch| ch != ' ').unwrap_or(0);
157157
let space = &blockquote[..initial_spaces];
158+
if lower.starts_with("edition-") {
159+
let edition = &lower[8..];
160+
return format!("{space}<div class=\"alert alert-edition\">\n\
161+
\n\
162+
{space}> <p class=\"alert-title\">\
163+
<span class=\"alert-title-edition\">{edition}</span> Edition differences</p>\n\
164+
{space} >\n\
165+
{blockquote}\n\
166+
\n\
167+
{space}</div>\n");
168+
}
169+
158170
// These icons are from GitHub, MIT License, see https://github.com/primer/octicons
159171
let svg = match lower.as_str() {
160172
"note" => "<path d=\"M0 8a8 8 0 1 1 16 0A8 8 0 0 1 0 8Zm8-6.5a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13ZM6.5 7.75A.75.75 0 0 1 7.25 7h1a.75.75 0 0 1 .75.75v2.75h.25a.75.75 0 0 1 0 1.5h-2a.75.75 0 0 1 0-1.5h.25v-2h-.25a.75.75 0 0 1-.75-.75ZM8 6a1 1 0 1 1 0-2 1 1 0 0 1 0 2Z\"></path>",

src/abi.md

+6-3
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ with the same name (or with a well-known symbol), leading to undefined behavior.
7474
extern "C" fn foo() {}
7575
```
7676

77-
> **Edition differences**: Before the 2024 edition it is allowed to use the `no_mangle` attribute without the `unsafe` qualification.
77+
> [!EDITION-2024]
78+
> Before the 2024 edition it is allowed to use the `no_mangle` attribute without the `unsafe` qualification.
7879
7980
## The `link_section` attribute
8081

@@ -92,7 +93,8 @@ of memory not expecting them, such as mutable data into read-only areas.
9293
pub static VAR1: u32 = 1;
9394
```
9495

95-
> **Edition differences**: Before the 2024 edition it is allowed to use the `link_section` attribute without the `unsafe` qualification.
96+
> [!EDITION-2024]
97+
> Before the 2024 edition it is allowed to use the `link_section` attribute without the `unsafe` qualification.
9698
9799
## The `export_name` attribute
98100

@@ -109,7 +111,8 @@ behavior.
109111
pub fn name_in_rust() { }
110112
```
111113

112-
> **Edition differences**: Before the 2024 edition it is allowed to use the `export_name` attribute without the `unsafe` qualification.
114+
> [!EDITION-2024]
115+
> Before the 2024 edition it is allowed to use the `export_name` attribute without the `unsafe` qualification.
113116
114117
[_MetaNameValueStr_]: attributes.md#meta-item-attribute-syntax
115118
[`static` items]: items/static-items.md

src/destructors.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,8 @@ smallest scope that contains the expression and is one of the following:
215215
> The [scrutinee] of a `match` expression is not a temporary scope, so temporaries in the scrutinee can be dropped after the `match` expression. For example, the temporary for `1` in `match 1 { ref mut z => z };` lives until the end of the statement.
216216
217217
r[destructors.scope.temporary.edition2024]
218-
> **Edition differences**: The 2024 edition added two new temporary scope narrowing rules: `if let` temporaries are dropped before the `else` block, and temporaries of tail expressions of blocks are dropped immediately after the tail expression is evaluated.
218+
> [!EDITION-2024]
219+
> The 2024 edition added two new temporary scope narrowing rules: `if let` temporaries are dropped before the `else` block, and temporaries of tail expressions of blocks are dropped immediately after the tail expression is evaluated.
219220
220221
Some examples:
221222

src/expressions/await-expr.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@ More specifically, an await expression has the following effect.
2727
5. If the call to `poll` returns [`Poll::Pending`], then the future returns `Poll::Pending`, suspending its state so that, when the surrounding async context is re-polled,execution returns to step 3;
2828
6. Otherwise the call to `poll` must have returned [`Poll::Ready`], in which case the value contained in the [`Poll::Ready`] variant is used as the result of the `await` expression itself.
2929

30-
> **Edition differences**: Await expressions are only available beginning with Rust 2018.
30+
r[expr.await.edition2018]
31+
> [!EDITION-2018]
32+
> Await expressions are only available beginning with Rust 2018.
3133
3234
r[expr.await.task]
3335
## Task context

src/expressions/block-expr.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,9 @@ The actual data format for this type is unspecified.
114114
> [!NOTE]
115115
> The future type that rustc generates is roughly equivalent to an enum with one variant per `await` point, where each variant stores the data needed to resume from its corresponding point.
116116
117-
> **Edition differences**: Async blocks are only available beginning with Rust 2018.
117+
r[expr.block.async.edition2018]
118+
> [!EDITION-2018]
119+
> Async blocks are only available beginning with Rust 2018.
118120
119121
r[expr.block.async.capture]
120122
### Capture modes

src/expressions/closure-expr.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,8 @@ async fn example() {
7878
```
7979

8080
r[expr.closure.async.edition2018]
81-
> **Edition differences**: Async closures are only available beginning with Rust 2018.
81+
> [!EDITION-2018]
82+
> Async closures are only available beginning with Rust 2018.
8283
8384
## Example
8485

src/expressions/method-call-expr.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,9 @@ r[expr.method.ambiguous-search]
7979
If a step is reached where there is more than one possible method, such as where generic methods or traits are considered the same, then it is a compiler error.
8080
These cases require a [disambiguating function call syntax] for method and function invocation.
8181
82-
> **Edition differences**: Before the 2021 edition, during the search for visible methods, if the candidate receiver type is an [array type], methods provided by the standard library [`IntoIterator`] trait are ignored.
82+
r[expr.method.edition2021]
83+
> [!EDITION-2021]
84+
> Before the 2021 edition, during the search for visible methods, if the candidate receiver type is an [array type], methods provided by the standard library [`IntoIterator`] trait are ignored.
8385
>
8486
> The edition used for this purpose is determined by the token representing the method name.
8587
>

src/introduction.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -78,9 +78,10 @@ These conventions are documented here.
7878

7979
An *example term* is an example of a term being defined.
8080

81-
* Differences in the language by which edition the crate is compiled under are in a blockquote that start with the words "Edition differences:" in **bold**.
81+
* The main text describes the latest stable edition. Differences to previous editions are separated in edition blocks:
8282

83-
> **Edition differences**: In the 2015 edition, this syntax is valid that is disallowed as of the 2018 edition.
83+
> [!EDITION-2018]
84+
> In the 2015 edition, this syntax is valid that is disallowed as of the 2018 edition.
8485
8586
* Notes that contain useful information about the state of the book or point out useful, but mostly out of scope, information are in note blocks.
8687

src/items/associated-items.md

+3-4
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,9 @@ let circle_shape = Circle::new();
211211
let bounding_box = circle_shape.bounding_box();
212212
```
213213

214-
r[items.associated.fn.params.edition2015]
215-
> **Edition differences**: In the 2015 edition, it is possible to declare trait
216-
> methods with anonymous parameters (e.g. `fn foo(u8)`). This is deprecated and
217-
> an error as of the 2018 edition. All parameters must have an argument name.
214+
r[items.associated.fn.params.edition2018]
215+
> [!EDITION-2018]
216+
> In the 2015 edition, it is possible to declare trait methods with anonymous parameters (e.g. `fn foo(u8)`). This is deprecated and an error as of the 2018 edition. All parameters must have an argument name.
218217
219218
r[items.associated.fn.param-attributes]
220219
#### Attributes on method parameters

src/items/external-blocks.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ r[items.extern.unsafe-required]
3636
The `unsafe` keyword is semantically required to appear before the `extern` keyword on external blocks.
3737

3838
r[items.extern.edition2024]
39-
> **Edition differences**: Prior to the 2024 edition, the `unsafe` keyword is optional. The `safe` and `unsafe` item qualifiers are only allowed if the external block itself is marked as `unsafe`.
39+
> [!EDITION-2024]
40+
> Prior to the 2024 edition, the `unsafe` keyword is optional. The `safe` and `unsafe` item qualifiers are only allowed if the external block itself is marked as `unsafe`.
4041
4142
r[items.extern.fn]
4243
## Functions

src/items/functions.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ For more information on the effect of async, see [`async` blocks][async-blocks].
360360
[`impl Future`]: ../types/impl-trait.md
361361

362362
r[items.fn.async.edition2018]
363-
> **Edition differences**: Async functions are only available beginning with
364-
> Rust 2018.
363+
> [!EDITION-2018]
364+
> Async functions are only available beginning with Rust 2018.
365365
366366
r[items.fn.async.safety]
367367
### Combining `async` and `unsafe`

src/items/use-declarations.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,9 @@ fn example() {
138138
}
139139
```
140140

141-
r[items.use.path.edition2015]
142-
> **Edition differences**: In the 2015 edition, `use` paths are relative to the crate root.
143-
> For example:
141+
r[items.use.path.edition2018]
142+
> [!EDITION-2018]
143+
> In the 2015 edition, `use` paths are relative to the crate root. For example:
144144
>
145145
> ```rust,edition2015
146146
> mod foo {
@@ -196,8 +196,9 @@ r[items.use.multiple-syntax.empty]
196196
An empty brace does not import anything, though the leading path is validated that it is accessible.
197197
<!-- This is slightly wrong, see: https://github.com/rust-lang/rust/issues/61826 -->
198198

199-
r[items.use.multiple-syntax.edition2015]
200-
> **Edition differences**: In the 2015 edition, paths are relative to the crate root, so an import such as `use {foo, bar};` will import the names `foo` and `bar` from the crate root, whereas starting in 2018, those names are relative to the current scope.
199+
r[items.use.multiple-syntax.edition2018]
200+
> [!EDITION-2018]
201+
> In the 2015 edition, paths are relative to the crate root, so an import such as `use {foo, bar};` will import the names `foo` and `bar` from the crate root, whereas starting in 2018, those names are relative to the current scope.
201202
202203
r[items.use.self]
203204
## `self` imports
@@ -307,9 +308,9 @@ r[items.use.glob.last-segment-only]
307308
r[items.use.glob.self-import]
308309
`*` cannot be used to import a module's contents into itself (such as `use self::*;`).
309310

310-
r[items.use.glob.edition2015]
311-
> **Edition differences**: In the 2015 edition, paths are relative to the crate root, so an import such as `use *;` is valid, and it means to import everything from the crate root.
312-
> This cannot be used in the crate root itself.
311+
r[items.use.glob.edition2018]
312+
> [!EDITION-2018]
313+
> In the 2015 edition, paths are relative to the crate root, so an import such as `use *;` is valid, and it means to import everything from the crate root. This cannot be used in the crate root itself.
313314
314315
r[items.use.as-underscore]
315316
## Underscore Imports

src/macros-by-example.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -160,14 +160,16 @@ The keyword metavariable `$crate` can be used to refer to the current crate; see
160160
transcribed more than once or not at all.
161161

162162
r[macro.decl.meta.edition2021]
163-
> **Edition differences**: Starting with the 2021 edition, `pat` fragment-specifiers match top-level or-patterns (that is, they accept [_Pattern_]).
163+
> [!EDITION-2021]
164+
> Starting with the 2021 edition, `pat` fragment-specifiers match top-level or-patterns (that is, they accept [_Pattern_]).
164165
>
165166
> Before the 2021 edition, they match exactly the same fragments as `pat_param` (that is, they accept [_PatternNoTopAlt_]).
166167
>
167168
> The relevant edition is the one in effect for the `macro_rules!` definition.
168169
169170
r[macro.decl.meta.edition2024]
170-
> **Edition differences**: Before the 2024 edition, `expr` fragment specifiers do not match [_UnderscoreExpression_] or [_ConstBlockExpression_] at the top level. They are allowed within subexpressions.
171+
> [!EDITION-2024]
172+
> Before the 2024 edition, `expr` fragment specifiers do not match [_UnderscoreExpression_] or [_ConstBlockExpression_] at the top level. They are allowed within subexpressions.
171173
>
172174
> The `expr_2021` fragment specifier exists to maintain backwards compatibility with editions before 2024.
173175
@@ -496,7 +498,7 @@ macro_rules! call_foo {
496498
fn foo() {}
497499
```
498500

499-
> **Version & Edition differences**: Prior to Rust 1.30, `$crate` and
501+
> **Version differences**: Prior to Rust 1.30, `$crate` and
500502
> `local_inner_macros` (below) were unsupported. They were added alongside
501503
> path-based imports of macros (described above), to ensure that helper macros
502504
> did not need to be manually imported by users of a macro-exporting crate.
@@ -567,7 +569,8 @@ r[macro.decl.follow-set.token-other]
567569
* All other fragment specifiers have no restrictions.
568570

569571
r[macro.decl.follow-set.edition2021]
570-
> **Edition differences**: Before the 2021 edition, `pat` may also be followed by `|`.
572+
> [!EDITION-2021]
573+
> Before the 2021 edition, `pat` may also be followed by `|`.
571574
572575
r[macro.decl.follow-set.repetition]
573576
When repetitions are involved, then the rules apply to every possible number of

src/names/preludes.md

+5-9
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,10 @@ r[names.preludes.extern.std]
5757
The [`std`] crate is added as long as the [`no_std` attribute] is not specified in the crate root.
5858

5959
r[names.preludes.extern.edition2018]
60-
> **Edition differences**: In the 2015 edition, crates in the extern prelude
61-
> cannot be referenced via [use declarations], so it is generally standard
62-
> practice to include `extern crate` declarations to bring them into scope.
60+
> [!EDITION-2018]
61+
> In the 2015 edition, crates in the extern prelude cannot be referenced via [use declarations], so it is generally standard practice to include `extern crate` declarations to bring them into scope.
6362
>
64-
> Beginning in the 2018 edition, [use declarations] can reference crates in
65-
> the extern prelude, so it is considered unidiomatic to use `extern crate`.
63+
> Beginning in the 2018 edition, [use declarations] can reference crates in the extern prelude, so it is considered unidiomatic to use `extern crate`.
6664
6765
> [!NOTE]
6866
> Additional crates that ship with `rustc`, such as [`alloc`], and [`test`](mod@test), are not automatically included with the `--extern` flag when using Cargo. They must be brought into scope with an `extern crate` declaration, even in the 2018 edition.
@@ -155,10 +153,8 @@ r[names.preludes.no_implicit_prelude.lang]
155153
This attribute does not affect the [language prelude].
156154
157155
r[names.preludes.no_implicit_prelude.edition2018]
158-
> **Edition differences**: In the 2015 edition, the `no_implicit_prelude`
159-
> attribute does not affect the [`macro_use` prelude], and all macros exported
160-
> from the standard library are still included in the `macro_use` prelude.
161-
> Starting in the 2018 edition, it will remove the `macro_use` prelude.
156+
> [!EDITION-2018]
157+
> In the 2015 edition, the `no_implicit_prelude` attribute does not affect the [`macro_use` prelude], and all macros exported from the standard library are still included in the `macro_use` prelude. Starting in the 2018 edition, it will remove the `macro_use` prelude.
162158
163159
[`extern crate`]: ../items/extern-crates.md
164160
[`macro_use` attribute]: ../macros-by-example.md#the-macro_use-attribute

src/paths.md

+4-7
Original file line numberDiff line numberDiff line change
@@ -188,14 +188,11 @@ Paths starting with `::` are considered to be *global paths* where the segments
188188
start being resolved from a place which differs based on edition. Each identifier in
189189
the path must resolve to an item.
190190

191-
r[paths.qualifiers.global-root.edition2015]
192-
> **Edition Differences**: In the 2015 Edition, identifiers resolve from the "crate root"
193-
> (`crate::` in the 2018 edition), which contains a variety of different items, including
194-
> external crates, default crates such as `std` or `core`, and items in the top level of
195-
> the crate (including `use` imports).
191+
r[paths.qualifiers.global-root.edition2018]
192+
> [!EDITION-2018]
193+
> In the 2015 Edition, identifiers resolve from the "crate root" (`crate::` in the 2018 edition), which contains a variety of different items, including external crates, default crates such as `std` or `core`, and items in the top level of the crate (including `use` imports).
196194
>
197-
> Beginning with the 2018 Edition, paths starting with `::` resolve from
198-
> crates in the [extern prelude]. That is, they must be followed by the name of a crate.
195+
> Beginning with the 2018 Edition, paths starting with `::` resolve from crates in the [extern prelude]. That is, they must be followed by the name of a crate.
199196
200197
```rust
201198
pub fn foo() {

src/patterns.md

+6-3
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,8 @@ let [ref mut x] = &mut [()]; //~ ERROR
334334
```
335335

336336
r[patterns.ident.binding.mode-limitations.edition2024]
337-
> **Edition differences**: Before the 2024 edition, bindings could explicitly specify a `ref` or `ref mut` binding mode even when the default binding mode was not "move", and they could specify mutability on such bindings with `mut`. In these editions, specifying `mut` on a binding set the binding mode to "move" regardless of the current default binding mode.
337+
> [!EDITION-2024]
338+
> Before the 2024 edition, bindings could explicitly specify a `ref` or `ref mut` binding mode even when the default binding mode was not "move", and they could specify mutability on such bindings with `mut`. In these editions, specifying `mut` on a binding set the binding mode to "move" regardless of the current default binding mode.
338339
339340
r[patterns.ident.binding.mode-limitations-reference]
340341
Similarly, a reference pattern may only appear when the default binding mode is "move". For example, this is not accepted:
@@ -344,7 +345,8 @@ let [&x] = &[&()]; //~ ERROR
344345
```
345346

346347
r[patterns.ident.binding.mode-limitations-reference.edition2024]
347-
> **Edition differences**: Before the 2024 edition, reference patterns could appear even when the default binding mode was not "move", and had both the effect of matching against the scrutinee and of causing the default binding mode to be reset to "move".
348+
> [!EDITION-2024]
349+
> Before the 2024 edition, reference patterns could appear even when the default binding mode was not "move", and had both the effect of matching against the scrutinee and of causing the default binding mode to be reset to "move".
348350
349351
r[patterns.ident.binding.mixed]
350352
Move bindings and reference bindings can be mixed together in the same pattern.
@@ -669,7 +671,8 @@ _RangeFromPattern_ cannot be used as a top-level pattern for subpatterns in [sli
669671
For example, the pattern `[1.., _]` is not a valid pattern.
670672

671673
r[patterns.range.edition2021]
672-
> **Edition differences**: Before the 2021 edition, range patterns with both a lower and upper bound may also be written using `...` in place of `..=`, with the same meaning.
674+
> [!EDITION-2021]
675+
> Before the 2021 edition, range patterns with both a lower and upper bound may also be written using `...` in place of `..=`, with the same meaning.
673676
674677
r[patterns.ref]
675678
## Reference patterns

0 commit comments

Comments
 (0)