This page documents two related systems that underpin all compilation phases:
Symbol type in rustc_span, which provides efficiently interned strings used for identifiers, keywords, and attribute names throughout the compiler.rustc_feature crate's machinery for classifying stable, unstable, and removed language features, the built-in attribute registry, and how gate checking is enforced during compilation.For how attributes are parsed and structurally validated after feature gate checks, see Attribute Processing and Validation (3.6). For the span and source location infrastructure that shares rustc_span with symbols, see Span and Source Location Tracking (3.5). For how the type context and query system consume features at later phases, see Type Context and Query System (3.1).
Symbol TypeSymbol is a u32 newtype defined in compiler/rustc_span/src/symbol.rs that represents an interned string. Two Symbol values are equal if and only if they represent the same string, making equality comparison O(1) regardless of string length.
The primary API:
Symbol::intern(s: &str) -> Symbol — looks up or inserts a string, returning its index.sym.as_str() -> &str — retrieves the underlying string for the duration of the session.Symbol::as_u32(self) -> u32 — extracts the raw index.Symbol derives Copy, Clone, Hash, Eq, Ord, and implements HashStable for incremental compilation. It can be stored directly in hash maps and sorted collections without heap allocation.
Interning architecture (Symbol type)
Sources: compiler/rustc_span/src/symbol.rs1-18
InternerThe Interner struct stores string data in a DroplessArena (which avoids running destructors on the stored &str slices) and tracks the string-to-index mapping in an FxIndexSet. All access goes through a Lock to allow concurrent symbol interning during parallel compilation.
The SessionGlobals struct, allocated once per compiler session, holds the live Interner. Access is always via the with_session_globals closure:
Sources: compiler/rustc_span/src/symbol.rs1-18
symbols! MacroStrings that are known at compile time (all keywords, attribute names, lang-item names, etc.) are pre-interned at session startup so their Symbol values are compile-time constants. The symbols! macro invocation in compiler/rustc_span/src/symbol.rs23-1406 handles this.
The macro is implemented in compiler/rustc_macros/src/symbols.rs and generates two constant namespaces:
| Namespace | Module | Populated from | Example constants |
|---|---|---|---|
kw::* | rustc_span::symbol::kw | Keywords { } block | kw::If, kw::Fn, kw::Async |
sym::* | rustc_span::symbol::sym | Symbols { } block | sym::feature, sym::inline, sym::cfg |
Keywords are assigned sequential u32 indices beginning at 0; sym::* constants follow immediately after.
The digit strings "0" through "9" are accessible via the helper sym::integer(n: u32) -> Symbol.
Pre-interned symbol namespace generation
Sources: compiler/rustc_span/src/symbol.rs22-155
The Symbol type exposes predicate methods to classify keywords. These are used by the parser and lexer:
| Predicate method | Applies to |
|---|---|
is_special() | $crate, {{root}}, _ |
is_used_keyword_always() | Stable keywords: if, fn, let, while, etc. |
is_unused_keyword_always() | Reserved identifiers: abstract, become, box, do, final, yield, etc. |
is_used_keyword_conditional(edition) | Edition-gated stable: async, await, dyn (≥ 2018), gen (≥ 2024) |
is_unused_keyword_conditional(edition) | Edition-gated reserved: try (≥ 2018) |
is_weak() | Contextual keywords: union, default, auto, macro_rules, safe, raw |
is_reserved(edition) | Union of the used/unused predicates above |
Sources: compiler/rustc_span/src/symbol.rs32-139
The rustc_feature crate defines the full catalogue of language features and controls whether they are accessible to user code. Features exist in three states:
| State | Source file | Description |
|---|---|---|
| Unstable | compiler/rustc_feature/src/unstable.rs | Under development or consideration |
| Accepted | compiler/rustc_feature/src/accepted.rs | Stabilized; available on stable Rust |
| Removed | compiler/rustc_feature/src/removed.rs | Previously unstable, now gone |
Features StructFeatures is constructed at the start of compilation from all #![feature(...)] attributes on the crate root and stored in the Session. It is the authoritative source of which features are active for a given compilation.
compiler/rustc_feature/src/unstable.rs39-46
EnabledLangFeature captures:
gate_name: Symbol — the feature name symbol.attr_sp: Span — span of the #![feature(...)] attribute for error reporting.stable_since: Option<Symbol> — version string if the feature has been accepted.Two equivalent ways to test whether a feature is active:
tcx.features().foo() — preferred; direct generated method.tcx.features().enabled(sym::foo) — use when the feature name is not a constant.Sources: compiler/rustc_feature/src/unstable.rs39-108
Within the unstable.rs file, each unstable feature carries one of three statuses controlled by the leading keyword in declare_features!:
| Keyword | FeatureStatus variant | Effect |
|---|---|---|
unstable | Default | Normal unstable; requires #![feature(...)] on nightly |
incomplete | Incomplete | Likely to cause ICEs; additional warning emitted |
internal | Internal | Compiler/stdlib internals; warning discourages use |
Sources: compiler/rustc_feature/src/unstable.rs12-28
declare_features! MacroAll unstable features are registered via a single declare_features! invocation in compiler/rustc_feature/src/unstable.rs192 The macro syntax is:
(status, feature_name, "since_version", issue_number),
Example entries:
(unstable, let_chains, "1.37.0", Some(88642)),
(incomplete, async_drop, "1.88.0", Some(126482)),
(internal, lang_items, "1.0.0", None),
The macro generates:
UNSTABLE_LANG_FEATURES: &[Feature] — a static array consumed by tools like tidy.pub fn foo(&self) -> bool method on Features for every feature.Features::incomplete(feature: Symbol) -> bool.Features::internal(feature: Symbol) -> bool.Feature gate system: code entities
Sources: compiler/rustc_feature/src/unstable.rs110-172 compiler/rustc_ast_passes/src/feature_gate.rs1-10
Gate checking runs as an AST visitor defined in compiler/rustc_ast_passes/src/feature_gate.rs. It executes after macro expansion on the fully expanded AST. The visitor:
Features::enabled(gate_symbol).#![feature(...)] location.incomplete or internal: emits an additional warning.The visitor integrates with BUILTIN_ATTRIBUTES (see below) to gate attribute usage without needing separate checks for every attribute in the visitor body.
Sources: compiler/rustc_ast_passes/src/feature_gate.rs1-10
compiler/rustc_feature/src/builtin_attrs.rs defines the static registry of all built-in compiler attributes. It is used during attribute validation to determine whether an attribute is recognized and under what conditions it may be used.
AttributeGateControls when a built-in attribute is accessible:
Ungated — always available on stable Rust.Gated(Stability, Symbol, &str, fn(&Features) -> bool) — the attribute requires a feature to be enabled. The function pointer is the gate check.AttributeTypeClassifies where an attribute may syntactically appear:
| Variant | Meaning |
|---|---|
Normal | Outer attribute on an item |
CrateLevel | Inner crate-level (#![...]) only |
WhereClause | Appears in where clauses |
AttributeDuplicatesControls behavior when an attribute appears multiple times on the same item:
| Variant | Behavior |
|---|---|
DuplicatesOk | Multiple instances allowed |
WarnFollowing | Warn on all but the first |
ErrorFollowing | Error on all but the first |
ErrorPreceding | Error on all but the last |
FutureWarnFollowing | Future-compatibility warning |
cfg FlagsGATED_CFGS in compiler/rustc_feature/src/builtin_attrs.rs21-37 lists cfg(...) predicates that are themselves feature-gated. The type alias is:
| cfg predicate | Required feature gate |
|---|---|
overflow_checks | cfg_overflow_checks |
ub_checks | cfg_ub_checks |
contract_checks | cfg_contract_checks |
target_thread_local | cfg_target_thread_local |
sanitize | cfg_sanitize |
target_has_atomic_equal_alignment | cfg_target_has_atomic_equal_alignment |
Sources: compiler/rustc_feature/src/builtin_attrs.rs1-37
#[target_feature] and #[cfg(target_feature)] have their own stability model, separate from language feature gates, defined in compiler/rustc_target/src/target_features.rs.
Stability Enumcompiler/rustc_target/src/target_features.rs16-68
Stability
├── Stable
│ Available in #[target_feature] and cfg(target_feature) on stable Rust
├── Unstable(Symbol)
│ Nightly only; Symbol is the required language feature gate
└── Forbidden { reason: &'static str }
Cannot be set via #[target_feature] or -Ctarget-feature
Used for features that change the calling ABI
Key methods:
Stability::in_cfg(&self) -> bool — whether the feature may appear in cfg(target_feature).Stability::requires_nightly(&self) -> Option<Symbol> — the required nightly gate, if any.Stability::toggle_allowed(&self) -> Result<(), &str> — whether #[target_feature] may toggle this feature.Target feature stability model
Sources: compiler/rustc_target/src/target_features.rs16-68
Each supported architecture has a static array of (&str, Stability, ImpliedFeatures) triples. Enabling a feature also enables all features in its ImpliedFeatures list, transitively.
| Static | Architecture |
|---|---|
ARM_FEATURES | 32-bit ARM |
AARCH64_FEATURES | AArch64 |
X86_FEATURES | x86 / x86-64 |
RISCV_FEATURES | RISC-V |
MIPS_FEATURES | MIPS |
LOONGARCH_FEATURES | LoongArch |
RUSTC_SPECIFIC_FEATURES is a separate list of features that control rustc behavior rather than codegen — currently just crt-static.
Sources: compiler/rustc_target/src/target_features.rs12-116
Compilation flow: symbols and gates
Sources: compiler/rustc_span/src/symbol.rs1-18 compiler/rustc_feature/src/unstable.rs39-108 compiler/rustc_feature/src/builtin_attrs.rs1-37 compiler/rustc_ast_passes/src/feature_gate.rs1-10
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.