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(Clone, Copy, Debug, Hash)]
44pub enum UnstableFeatures {
45 Disallow,
47 Allow,
49 Cheat,
54}
55
56impl UnstableFeatures {
57 pub fn from_environment(krate: Option<&str>) -> Self {
62 Self::from_environment_value(krate, std::env::var("RUSTC_BOOTSTRAP"))
63 }
64
65 fn from_environment_value(
69 krate: Option<&str>,
70 env_var_rustc_bootstrap: Result<String, std::env::VarError>,
71 ) -> Self {
72 let disable_unstable_features =
74 option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some_and(|s| s != "0");
75 let is_unstable_crate =
77 |var: &str| krate.is_some_and(|name| var.split(',').any(|new_krate| new_krate == name));
78
79 let bootstrap = env_var_rustc_bootstrap.ok();
80 if let Some(val) = bootstrap.as_deref() {
81 match val {
82 val if val == "1" || is_unstable_crate(val) => return UnstableFeatures::Cheat,
83 "-1" => return UnstableFeatures::Disallow,
86 _ => {}
87 }
88 }
89
90 if disable_unstable_features { UnstableFeatures::Disallow } else { UnstableFeatures::Allow }
91 }
92
93 pub fn is_nightly_build(&self) -> bool {
94 match *self {
95 UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
96 UnstableFeatures::Disallow => false,
97 }
98 }
99}
100
101fn find_lang_feature_issue(feature: Symbol) -> Option<NonZero<u32>> {
102 if let Some(f) = UNSTABLE_LANG_FEATURES.iter().find(|f| f.name == feature) {
104 return f.issue;
105 }
106 if let Some(f) = ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature) {
107 return f.issue;
108 }
109 if let Some(f) = REMOVED_LANG_FEATURES.iter().find(|f| f.feature.name == feature) {
110 return f.feature.issue;
111 }
112 panic!("feature `{feature}` is not declared anywhere");
113}
114
115const fn to_nonzero(n: Option<u32>) -> Option<NonZero<u32>> {
116 match n {
119 None => None,
120 Some(n) => NonZero::new(n),
121 }
122}
123
124pub enum GateIssue {
125 Language,
126 Library(Option<NonZero<u32>>),
127}
128
129pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u32>> {
130 match issue {
131 GateIssue::Language => find_lang_feature_issue(feature),
132 GateIssue::Library(lib) => lib,
133 }
134}
135
136pub use accepted::ACCEPTED_LANG_FEATURES;
137pub use builtin_attrs::{
138 AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType,
139 BUILTIN_ATTRIBUTE_MAP, BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg, encode_cross_crate,
140 find_gated_cfg, is_builtin_attr_name, is_stable_diagnostic_attribute, is_valid_for_get_attr,
141};
142pub use removed::REMOVED_LANG_FEATURES;
143pub use unstable::{
144 EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, UNSTABLE_LANG_FEATURES,
145};