Nightly and Unstable Features

Purpose and Scope

Rust has a stable language and library surface, but it also has an intentionally visible experimentation path. A nightly feature is a language or library capability that can be tried before it becomes part of stable Rust. An unstable feature is accessed through a feature gate, usually written as a crate-level attribute such as #![feature(coroutines)]. The official Unstable Book frames its chapters around these feature flags and warns readers that unstable documentation is maintained on a best-effort basis, so the tracking issue for a feature remains an important source of current status.

In this repository, that user-facing story maps to compiler data structures that remember which gates a crate enabled and to registry files that separate still-unstable gates from formerly unstable gates that have been accepted. The root README establishes this repository as the main source tree for the Rust compiler, standard library, and documentation, which matters because feature gates are not just documentation entries: they are part of how the compiler controls access to evolving language and library behavior. Sources: README.md, compiler/rustc_feature/src/unstable.rs, compiler/rustc_feature/src/accepted.rs

Nightly is therefore best understood as a channel for coordinated experimentation rather than as a different language. The same repository contains the compiler machinery, the library code, and the documentation links that teach users where to start. Stable users normally follow The Book, the Reference, standard library docs, and Cargo workflows; nightly users add one more question before adopting a capability: is the feature still guarded, incomplete, internal, or accepted into stable Rust? That question is answered partly by public documentation and partly by the compiler feature registry.

Relevant Source Files

  • README.md — identifies this as the main Rust source repository containing the compiler, standard library, and documentation, and links readers to the main documentation surfaces.
  • compiler/rustc_feature/src/unstable.rs — defines the unstable feature-gate list support, the Features collection, enabled language and library feature records, and the runtime checks used by later compiler passes.
  • compiler/rustc_feature/src/accepted.rs — defines ACCEPTED_LANG_FEATURES, the registry of feature gates that were once unstable and have since been stabilized, including stabilization version and tracking issue metadata.

Documentation Model

The official documentation model is deliberately layered. Beginner material teaches stable Rust first, because stable Rust is the supported contract for most projects. The Unstable Book exists for readers who intentionally opt into nightly features and need chapter-level guidance for individual gates. Its example uses a crate attribute containing multiple feature names and then shows code that depends on those gated capabilities. That pattern is important: a feature gate is not a Cargo dependency and not a module import; it is a compiler-recognized declaration that the crate wants access to an unstable capability.

The root README reinforces that ordinary entry points begin with the website, Getting Started, Learn, Documentation, and The Book. It also describes Rust’s goals around reliability, performance, productivity, diagnostics, and tooling. Nightly features fit into that ecosystem as a controlled exception to the stable-first path. They are valuable for experimentation, compiler development, library evolution, and early adopter feedback, but they should not be mistaken for the same compatibility promise as stable language features. Sources: README.md

The Unstable Book’s warning about accuracy and tracking issues is not just legal caution; it reflects how Rust evolves. A feature can be redesigned, renamed, split, merged, removed, or stabilized. Documentation gives examples and intent, while the compiler feature registry determines what a specific compiler build recognizes. When a user sees an error asking for a feature gate, the practical next step is to identify the gate name, confirm that the nightly toolchain is being used, read the relevant Unstable Book chapter, and review the tracking issue for recent changes.

Compiler Feature-Gate Model

The central compiler-side abstraction in the supplied source is the Features struct. It stores enabled language features, enabled library features, and a combined set of enabled feature symbols. The split matters because Rust gates both syntax or semantic language behavior and library APIs. Later compiler passes can ask whether a feature is enabled either through a generated feature-specific method, which the comments prefer for language features, or through the more general enabled method when the symbol is dynamic or the gate is a library feature. Sources: compiler/rustc_feature/src/unstable.rs

The records stored inside Features keep diagnostic information, not only a boolean flag. EnabledLangFeature contains the gate name, the span of the #[feature(...)] attribute, and optional stabilization information for stable language features. EnabledLibFeature contains the gate name and attribute span. Keeping spans allows the compiler to point diagnostics back to the user’s source attribute, and keeping stabilization data lets the compiler produce more helpful messages when a feature no longer needs to be explicitly enabled.

The implementation also includes a combined FxHashSet<Symbol> for quick membership checks. When enabled(feature) finds a feature in that set, it calls TRACK_FEATURE(feature) before returning true. The source comment explains why this hook exists: recording used features in the dependency graph lets incremental compilation replay used features when needed. That detail shows that feature gates are not a superficial front-end list; they participate in compilation state, diagnostics, and incremental correctness. Sources: compiler/rustc_feature/src/unstable.rs

FeatureStatus distinguishes default unstable features from Incomplete and Internal categories. The macro mapping from textual status names to enum variants lets the registry express more than a yes-or-no unstable state. In practice, this helps the compiler and maintainers communicate different kinds of risk. An incomplete feature may exist for experimentation but not yet represent a coherent product surface. An internal feature is for compiler or standard-library implementation needs rather than general ecosystem use. Sources: compiler/rustc_feature/src/unstable.rs

Stabilization and Accepted Features

Stabilization has its own registry. The accepted feature source declares ACCEPTED_LANG_FEATURES, described in the file as formerly unstable features that have now been accepted, meaning stabilized. Each entry stores the feature name, the version in which it became stable, and an optional tracking issue. This is the compiler-side historical record that connects a previously gated capability to the stable language surface. Sources: compiler/rustc_feature/src/accepted.rs

The accepted list is maintained with process constraints. Comments in the source say entries are kept in alphabetical order and that tidy will fail if that order is not preserved. The same comments say that when moving an unstable feature into the accepted list, the version should be set to the current rustc version with spaces replaced by underscores. These details are contributor-facing, but they also explain why stabilization is a repository operation, not merely a documentation update. Sources: compiler/rustc_feature/src/accepted.rs

Several accepted entries illustrate the breadth of features that pass through gates. Examples in the supplied source include target features, ABIs, inline assembly options, associated constants and associated types, async and await, async closures, and async functions in traits. The list records when each became stable, such as async_await at 1.39.0 and async_fn_in_trait at 1.75.0. Those entries make stabilization visible as a sequence of concrete compiler-recognized transitions rather than a vague maturity label. Sources: compiler/rustc_feature/src/accepted.rs

Practical Workflow for Users

A user who wants to try an unstable capability should start with the stable documentation to understand the ordinary shape of the feature area, then switch to the Unstable Book for the specific gate. The minimum code-level signal is the crate attribute, placed at the crate root. For example, the Unstable Book demonstrates a pattern like this:

#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]

That attribute tells rustc which gates the crate requests. If the toolchain is stable, the request will not be accepted for ordinary unstable gates. If the toolchain is nightly, the compiler records the enabled gates in the Features structure and later passes can query them. The result is a controlled opt-in: code remains explicit about depending on unstable behavior, and compiler diagnostics can refer back to the attribute span when the request is wrong, obsolete, or unnecessary. Sources: compiler/rustc_feature/src/unstable.rs

For library authors, the most important operational rule is to avoid exposing accidental nightly requirements to stable users. A crate that uses #![feature(...)] generally requires nightly for consumers building that crate, unless the gated code is isolated behind appropriate configuration and not part of the stable build. Because the accepted registry keeps stabilization versions, a feature may eventually become usable without the attribute, but until that transition happens, the crate’s documentation should identify the nightly requirement and the exact gate names.

For contributors, the workflow is different. Adding, changing, or stabilizing a feature means updating compiler feature definitions, tests, documentation, and tracking issue state consistently. The accepted feature registry shows that stabilization records include the version and issue metadata, while the unstable machinery shows that enabled gates are used by later compiler passes. A feature gate therefore has to be treated as part of the compiler interface: spelling, status, diagnostics, incremental tracking, and documentation all need to remain aligned. Sources: compiler/rustc_feature/src/unstable.rs, compiler/rustc_feature/src/accepted.rs

Compact Reference

ConceptSource-level representationReader-facing meaning
Feature gate#![feature(...)] recognized as a SymbolExplicit opt-in to unstable Rust behavior on nightly
Enabled language featureEnabledLangFeatureGate name, source span, and optional stabilization version for diagnostics
Enabled library featureEnabledLibFeatureGate name and source span for non-language gated APIs
Enabled feature setFeatures::enabled_featuresFast membership set shared by language and library gates
Gate queryFeatures::enabled(Symbol)Returns whether the gate was requested and records use for incremental replay
Accepted featureACCEPTED_LANG_FEATURESFormerly unstable language feature that is now stable
Stabilization metadatasince and issue fieldsVersion and tracking issue associated with acceptance
Status categoryFeatureStatus::{Default, Incomplete, Internal}Maintainer signal about the kind of unstable gate

Next Steps

If you are learning Rust, treat nightly features as an advanced topic after the stable Book, Reference, and standard library documentation. If you are evaluating a specific nightly API, read its Unstable Book chapter, copy the exact feature names, and check the linked tracking issue before committing to it. If you are contributing to rustc, inspect the feature registry and accepted list together so that diagnostics, stabilization metadata, and documentation remain synchronized.

Related pages: overview, language-reference-overview, rustc-overview, compiler-architecture, standard-library-overview