You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: text/0000-checkpoints.md
+24-63Lines changed: 24 additions & 63 deletions
Original file line number
Diff line number
Diff line change
@@ -107,13 +107,13 @@ and represent a release in which several elements come together:
107
107
- The standard library and other core ecosystem crates have been updated to use the new features as appropriate.
108
108
- A new edition of the Rust Cookbook has been prepared, providing an updated set of guidance for which crates to use for various tasks.
109
109
110
-
The precise list of elements going into a epoch is expected to evolve over
110
+
The precise list of elements going into an epoch is expected to evolve over
111
111
time, as the Rust project and ecosystem grow.
112
112
113
113
Sometimes a feature we want to make available in a new epoch would require
114
114
backwards-incompatible changes, like introducing a new keyword. In that case,
115
115
the feature is only available by explicitly opting in to the new
116
-
epoch. Each **crate** can declare a epoch in its `Cargo.toml` like
116
+
epoch. Each **crate** can declare an epoch in its `Cargo.toml` like
117
117
`epoch = "2019"`; otherwise it is assumed to have epoch 2015,
118
118
coinciding with Rust 1.0. Thus, new epochs are *opt in*, and the
119
119
dependencies of a crate may use older or newer epochs than the crate
@@ -153,7 +153,7 @@ the next epoch**.
153
153
Rather, epochs, as their name suggests, represent a point of *global
154
154
coherence*, where documentation, tooling, the compiler, and core libraries are
155
155
all fully aligned on a new set of (already stabilized!) features and other
156
-
changes. This alignment can happen incrementally, but a epoch signals that
156
+
changes. This alignment can happen incrementally, but an epoch signals that
157
157
it *has* happened.
158
158
159
159
At the same time, epochs serve as a rallying point for making sure this
@@ -182,7 +182,7 @@ impetus for coming together as a community and putting together a polished produ
182
182
183
183
There's an important tension around stabilization and epochs:
184
184
185
-
- We want to enable new features, including those that require a epoch
185
+
- We want to enable new features, including those that require an epoch
186
186
opt-in, to be available on the stable channel as they become ready.
187
187
188
188
- That means that we must enable some form of the opt in before the epoch
@@ -193,36 +193,23 @@ There's an important tension around stabilization and epochs:
193
193
194
194
- That means that, once *any* form of the opt in is shipped, it cannot introduce *new* hard errors.
195
195
196
-
Thus, at some point within a epoch year, we will enable the opt-in on the
196
+
Thus, at some point within an epoch year, we will enable the opt-in on the
197
197
stable release channel, which must include *all* of the hard errors that will be
198
198
introduced in the next epoch, but not yet all of the stabilizations (or
199
199
other artifacts that go into the full epoch release). This is the *preview
200
200
period* for the epoch, which ends when a release is produced that
201
-
synchronizes all of the elements that go into a epoch and the epoch is
201
+
synchronizes all of the elements that go into an epoch and the epoch is
202
202
formally announced.
203
203
204
204
## A broad policy on epoch changes
205
205
206
206
There are numerous reasons to limit the scope of changes for new epochs, among them:
207
207
208
-
-**Limiting churn**. Even if you aren't *forced* to update your code, even if
209
-
there are automated tools to do so, churn is still a pain for existing
210
-
users. It also invalidates, or at least makes harder to use, existing content
211
-
on the internet, like StackOverflow answers and blog posts. And finally, it
212
-
plays against the important and hard work we've done to make Rust stable in
213
-
both reality and perception. In short, while epochs avoid *ecosystem* splits
214
-
and make churn opt-in, they do not eliminate *all* drawbacks.
215
-
216
-
-**Limiting technical debt**. The compiler retains compatibility for old
217
-
epochs, and thus must have distinct "modes" for dealing with them. We need to
218
-
strongly limit the amount and complexity of code needed for these modes, or
219
-
the compiler will become very difficult to maintain.
220
-
221
-
-**Limiting deep conceptual changes**. Just as we want to keep the compiler
222
-
maintainable, so too do we want to keep the conceptual model sustainable. That
223
-
is, if we make truly radical changes in a new epoch, it will be very
224
-
difficult for people to reason about code involving different epochs, or
225
-
to remember the precise differences.
208
+
-**Limiting churn**. Even if you aren't *forced* to update your code, even if there are automated tools to do so, churn is still a pain for existing users. It also invalidates, or at least makes harder to use, existing content on the internet, like StackOverflow answers and blog posts. And finally, it plays against the important and hard work we've done to make Rust stable in both reality and perception. In short, while epochs avoid *ecosystem* splits and make churn opt-in, they do not eliminate *all* drawbacks.
209
+
210
+
-**Limiting technical debt**. The compiler retains compatibility for old epochs, and thus must have distinct "modes" for dealing with them. We need to strongly limit the amount and complexity of code needed for these modes, or the compiler will become very difficult to maintain.
211
+
212
+
-**Limiting deep conceptual changes**. Just as we want to keep the compiler maintainable, so too do we want to keep the conceptual model sustainable. That is, if we make truly radical changes in a new epoch, it will be very difficult for people to reason about code involving different epochs, or to remember the precise differences.
226
213
227
214
These lead to some hard and soft constraints.
228
215
@@ -234,48 +221,24 @@ same behavior.**
234
221
There are only two things a new epoch can do that a normal release cannot:
235
222
236
223
- Change an existing deprecation into a hard error.
237
-
- This option is only available when the deprecation is expected to hit a
238
-
relatively small percentage of code.
239
-
- Change an existing deprecation to *deny* by default, and leverage the
240
-
corresponding lint setting to produce error messages *as if* the feature were
241
-
removed entirely.
242
-
243
-
The second option is to be preferred whenever possible. Note that warning-free
244
-
code in one epoch might produce warnings in the next epoch, but it should still
245
-
compile successfully.
246
-
247
-
The Rust compiler supports multiple epochs, but **must only support a single
248
-
version of "core Rust"**. We identify "core Rust" as being, roughly, MIR and the
249
-
core trait system; this specification will be made more precise over time. The
250
-
implication is that the "epoch modes" boil down to keeping around multiple
251
-
desugarings into this core Rust, which greatly limits the complexity and
252
-
technical debt involved. Similar, core Rust encompasses the core *conceptual*
253
-
model of the language, and this constraint guarantees that, even when working
254
-
with multiple epochs, those core concepts remain fixed.
224
+
- This option is only available when the deprecation is expected to hit a relatively small percentage of code.
225
+
- Change an existing deprecation to *deny* by default, and leverage the corresponding lint setting to produce error messages *as if* the feature were removed entirely.
226
+
227
+
The second option is to be preferred whenever possible. Note that warning-free code in one epoch might produce warnings in the next epoch, but it should still compile successfully.
228
+
229
+
The Rust compiler supports multiple epochs, but **must only support a single version of "core Rust"**. We identify "core Rust" as being, roughly, MIR and the core trait system; this specification will be made more precise over time. The implication is that the "epoch modes" boil down to keeping around multiple desugarings into this core Rust, which greatly limits the complexity and technical debt involved. Similar, core Rust encompasses the core *conceptual* model of the language, and this constraint guarantees that, even when working with multiple epochs, those core concepts remain fixed.
255
230
256
231
### Soft constraints
257
232
258
-
**TL;DR: *Most* code *with* warnings on epoch N should, after running `rustfix`,
259
-
compile on epoch N+1 and have the same behavior.**
233
+
**TL;DR: *Most* code *with* warnings on epoch N should, after running `rustfix`, compile on epoch N+1 and have the same behavior.**
260
234
261
-
The core epoch design avoids an ecosystem split, which is very important. But
262
-
it's *also* important that upgrading your own code to a new epoch is minimally
263
-
disruptive. The basic principle is that **changes that cannot be automated must
264
-
be required only in a small minority of crates, and even there not require
265
-
extensive work**. This principle applies not just to epochs, but also to cases
266
-
where we'd like to make a widespread deprecation.
235
+
The core epoch design avoids an ecosystem split, which is very important. But it's *also* important that upgrading your own code to a new epoch is minimally disruptive. The basic principle is that **changes that cannot be automated must be required only in a small minority of crates, and even there not require extensive work**. This principle applies not just to epochs, but also to cases where we'd like to make a widespread deprecation.
267
236
268
-
Note that a `rustfix` tool will never be perfect, because of conditional
269
-
compilation and code generation. So it's important that, in the cases it
270
-
inevitably fails, the manual fixes are not too onerous.
237
+
Note that a `rustfix` tool will never be perfect, because of conditional compilation and code generation. So it's important that, in the cases it inevitably fails, the manual fixes are not too onerous.
271
238
272
-
In addition, migrations that affect a large percentage of code must be "small
273
-
tweaks" (e.g. clarifying syntax), and as above, must keep the old form intact
274
-
(though they can enact a deny-by-default lint on it).
239
+
In addition, migrations that affect a large percentage of code must be "small tweaks" (e.g. clarifying syntax), and as above, must keep the old form intact (though they can enact a deny-by-default lint on it).
275
240
276
-
These are "soft constraints" because they use terms like "small minority" and
277
-
"small tweaks", which are open for interpretation. More broadly, the more
278
-
disruption involved, the higher the bar for the change.
241
+
These are "soft constraints" because they use terms like "small minority" and "small tweaks", which are open for interpretation. More broadly, the more disruption involved, the higher the bar for the change.
279
242
280
243
### Positive examples: What epoch opt-ins can do
281
244
@@ -369,7 +332,7 @@ Suppose we wanted to carry out such a change. We could do it over multiple steps
369
332
370
333
- First, introduce and stabilize `dyn Trait`.
371
334
- Deprecate bare `Trait` syntax in favor of `dyn Trait`.
372
-
- In a epoch preview period, make it an error to use bare `Trait` syntax.
335
+
- In an epoch preview period, make it an error to use bare `Trait` syntax.
373
336
- Ship the new epoch, and wait until bare `Trait` syntax is obscure.
374
337
- Re-introduce bare `Trait` syntax, stabilize it, and deprecate `impl Trait` in
375
338
favor of it.
@@ -435,7 +398,7 @@ We'll wrap up with the full details of the mechanisms at play.
435
398
-`Cargo.toml` can include an `epoch` value, which is used to pass to `rustc`.
436
399
- If left off, it will assume epoch 2015.
437
400
-`cargo new` will produce a `Cargo.toml` with the latest `epoch` value
438
-
(including a epoch currently in its preview period).
401
+
(including an epoch currently in its preview period).
439
402
440
403
# How We Teach This
441
404
[how-we-teach-this]: #how-we-teach-this
@@ -581,8 +544,6 @@ what kinds of changes we want to allow. Downsides:
581
544
582
545
- Is "epoch" the right key in Cargo.toml? Would it be more clear to just say `rust = "2019"`?
583
546
584
-
- Do we want to require a `rustfix` for all epoch changes?
585
-
586
547
- Will we ever consider dropping support for very old epochs? Given the
587
548
constraints in this RFC, it seems unlikely to ever be worth it.
0 commit comments