needs a tracking issue. General discussions about the feature should be done on the tracking issue.
For features that have an RFC, you should use the RFC's
tracking issue for the feature.
For other features, you'll have to make a tracking issue
for that feature. The issue title should be "Tracking issue
for YOUR FEATURE". Use the ["Tracking Issue" issue template][template].
## Stability in code
The below steps needs to be followed in order to implement
a new unstable feature:
1. Open a [tracking issue] -
if you have an RFC, you can use the tracking issue for the RFC.
The tracking issue should be labeled with at least `C-tracking-issue`.
For a language feature, a label `F-feature_name` should be added as well.
1. Pick a name for the feature gate (for RFCs, use the name
in the RFC).
1. Add the feature name to `rustc_span/src/symbol.rs` in the `Symbols {...}` block.
Note that this block must be in alphabetical order.
1. Add a feature gate declaration to `rustc_feature/src/unstable.rs` in the unstable
`declare_features` block.
```rust ignore
/// description of feature
(unstable, $feature_name, "CURRENT_RUSTC_VERSION", Some($tracking_issue_number))
```
If you haven't yet
opened a tracking issue (e.g. because you want initial feedback on whether the feature is likely
to be accepted), you can temporarily use `None` - but make sure to update it before the PR is
merged!
For example:
```rust ignore
/// Allows defining identifiers beyond ASCII.
(unstable, non_ascii_idents, "CURRENT_RUSTC_VERSION", Some(55467), None),
```
Features can be marked as incomplete, and trigger the warn-by-default [`incomplete_features`
lint]
by setting their type to `incomplete`:
```rust ignore
/// Allows unsized rvalues at arguments and parameters.
(incomplete, unsized_locals, "CURRENT_RUSTC_VERSION", Some(48055), None),
```
To avoid [semantic merge conflicts], please use `CURRENT_RUSTC_VERSION` instead of `1.70` or
another explicit version number.
1. Prevent usage of the new feature unless the feature gate is set.
You can check it in most places in the compiler using the
expression `tcx.features().$feature_name()`
If the feature gate is not set, you should either maintain
the pre-feature behavior or raise an error, depending on
what makes sense. Errors should generally use [`rustc_session::parse::feature_err`].
For an example of adding an error, see [#81015].
For features introducing new syntax, pre-expansion gating should be used instead.
During parsing, when the new syntax is parsed, the symbol must be inserted to the
current crate's [`GatedSpans`] via `self.sess.gated_span.gate(sym::my_feature, span)`.
After being inserted to the gated spans, the span must be checked in the
[`rustc_ast_passes::feature_gate::check_crate`] function, which actually denies
features. Exactly how it is gated depends on the exact type of feature, but most
likely will use the `gate_all!()` macro.
1. Add a test to ensure the feature cannot be used without
a feature gate, by creating `tests/ui/feature-gates/feature-gate-$feature_name.rs`.
You can generate the corresponding `.stderr` file by running `./x test
tests/ui/feature-gates/ --bless`.
1. Add a section to the unstable book, in
`src/doc/unstable-book/src/language-features/$feature_name.md`.
1. Write a lot of tests for the new feature, preferably in `tests/ui/$feature_name/`.
PRs without tests will not be accepted!
1. Get your PR reviewed and land it. You have now successfully
implemented a feature in Rust!