rustc_feature/
lib.rs
1#![allow(internal_features)]
16#![doc(rust_logo)]
17#![feature(rustdoc_internals)]
18mod accepted;
21mod builtin_attrs;
22mod removed;
23mod unstable;
24
25#[cfg(test)]
26mod tests;
27
28use std::num::NonZero;
29
30use rustc_span::Symbol;
31
32#[derive(Debug, Clone)]
33pub struct Feature {
34 pub name: Symbol,
35 pub since: &'static str,
40 issue: Option<NonZero<u32>>,
41}
42
43#[derive(Copy, Clone, Debug)]
44pub enum Stability {
45 Unstable,
46 Deprecated(&'static str, Option<&'static str>),
49}
50
51#[derive(Clone, Copy, Debug, Hash)]
52pub enum UnstableFeatures {
53 Disallow,
55 Allow,
57 Cheat,
62}
63
64impl UnstableFeatures {
65 pub fn from_environment(krate: Option<&str>) -> Self {
70 Self::from_environment_value(krate, std::env::var("RUSTC_BOOTSTRAP"))
71 }
72
73 fn from_environment_value(
77 krate: Option<&str>,
78 env_var_rustc_bootstrap: Result<String, std::env::VarError>,
79 ) -> Self {
80 let disable_unstable_features =
82 option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some_and(|s| s != "0");
83 let is_unstable_crate =
85 |var: &str| krate.is_some_and(|name| var.split(',').any(|new_krate| new_krate == name));
86
87 let bootstrap = env_var_rustc_bootstrap.ok();
88 if let Some(val) = bootstrap.as_deref() {
89 match val {
90 val if val == "1" || is_unstable_crate(val) => return UnstableFeatures::Cheat,
91 "-1" => return UnstableFeatures::Disallow,
94 _ => {}
95 }
96 }
97
98 if disable_unstable_features { UnstableFeatures::Disallow } else { UnstableFeatures::Allow }
99 }
100
101 pub fn is_nightly_build(&self) -> bool {
102 match *self {
103 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
104 UnstableFeatures::Disallow => false,
105 }
106 }
107}
108
109fn find_lang_feature_issue(feature: Symbol) -> Option<NonZero<u32>> {
110 if let Some(f) = UNSTABLE_LANG_FEATURES.iter().find(|f| f.name == feature) {
112 return f.issue;
113 }
114 if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature) {
115 return f.issue;
116 }
117 if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| f.feature.name == feature) {
118 return f.feature.issue;
119 }
120 panic!("feature `{feature}` is not declared anywhere");
121}
122
123const fn to_nonzero(n: Option<u32>) -> Option<NonZero<u32>> {
124 match n {
127 None => None,
128 Some(n) => NonZero::new(n),
129 }
130}
131
132pub enum GateIssue {
133 Language,
134 Library(Option<NonZero<u32>>),
135}
136
137pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u32>> {
138 match issue {
139 GateIssue::Language => find_lang_feature_issue(feature),
140 GateIssue::Library(lib) => lib,
141 }
142}
143
144pub use accepted::ACCEPTED_LANG_FEATURES;
145pub use builtin_attrs::{
146 AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType,
147 BUILTIN_ATTRIBUTE_MAP, BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg, deprecated_attributes,
148 encode_cross_crate, find_gated_cfg, is_builtin_attr_name, is_stable_diagnostic_attribute,
149 is_valid_for_get_attr,
150};
151pub use removed::REMOVED_LANG_FEATURES;
152pub use unstable::{
153 EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES,
154};