1mod accepted;
15mod builtin_attrs;
16mod removed;
17mod unstable;
18
19#[cfg(test)]
20mod tests;
21
22use std::num::NonZero;
23
24use rustc_span::Symbol;
25
26#[derive(Debug, Clone)]
27pub struct Feature {
28 pub name: Symbol,
29 pub since: &'static str,
34 issue: Option<NonZero<u32>>,
35}
36
37#[derive(Clone, Copy, Debug, Hash)]
38pub enum UnstableFeatures {
39 Disallow,
41 Allow,
43 Cheat,
48}
49
50impl UnstableFeatures {
51 pub fn from_environment(krate: Option<&str>) -> Self {
56 Self::from_environment_value(krate, std::env::var("RUSTC_BOOTSTRAP"))
57 }
58
59 fn from_environment_value(
63 krate: Option<&str>,
64 env_var_rustc_bootstrap: Result<String, std::env::VarError>,
65 ) -> Self {
66 let disable_unstable_features =
68 option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some_and(|s| s != "0");
69 let is_unstable_crate =
71 |var: &str| krate.is_some_and(|name| var.split(',').any(|new_krate| new_krate == name));
72
73 let bootstrap = env_var_rustc_bootstrap.ok();
74 if let Some(val) = bootstrap.as_deref() {
75 match val {
76 val if val == "1" || is_unstable_crate(val) => return UnstableFeatures::Cheat,
77 "-1" => return UnstableFeatures::Disallow,
80 _ => {}
81 }
82 }
83
84 if disable_unstable_features { UnstableFeatures::Disallow } else { UnstableFeatures::Allow }
85 }
86
87 pub fn is_nightly_build(&self) -> bool {
88 match *self {
89 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
90 UnstableFeatures::Disallow => false,
91 }
92 }
93}
94
95fn find_lang_feature_issue(feature: Symbol) -> Option<NonZero<u32>> {
96 if let Some(f) = UNSTABLE_LANG_FEATURES.iter().find(|f| f.name == feature) {
98 return f.issue;
99 }
100 if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature) {
101 return f.issue;
102 }
103 if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| f.feature.name == feature) {
104 return f.feature.issue;
105 }
106 panic!("feature `{feature}` is not declared anywhere");
107}
108
109const fn to_nonzero(n: Option<u32>) -> Option<NonZero<u32>> {
110 match n {
113 None => None,
114 Some(n) => NonZero::new(n),
115 }
116}
117
118pub enum GateIssue {
119 Language,
120 Library(Option<NonZero<u32>>),
121}
122
123pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u32>> {
124 match issue {
125 GateIssue::Language => find_lang_feature_issue(feature),
126 GateIssue::Library(lib) => lib,
127 }
128}
129
130pub use accepted::ACCEPTED_LANG_FEATURES;
131pub use builtin_attrs::{
132 AttrSuggestionStyle, AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate,
133 AttributeType, BUILTIN_ATTRIBUTE_MAP, BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg,
134 encode_cross_crate, find_gated_cfg, is_builtin_attr_name, is_stable_diagnostic_attribute,
135 is_valid_for_get_attr,
136};
137pub use removed::REMOVED_LANG_FEATURES;
138pub use unstable::{
139 EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES,
140};