]> git.lizzy.rs Git - rust.git/blob - src/librustc_feature/lib.rs
Account for `ty::Error` when suggesting `impl Trait` or `Box<dyn Trait>`
[rust.git] / src / librustc_feature / lib.rs
1 //! # Feature gates
2 //!
3 //! This crate declares the set of past and present unstable features in the compiler.
4 //! Feature gate checking itself is done in `librustc_ast_passes/feature_gate.rs`
5 //! at the moment.
6 //!
7 //! Features are enabled in programs via the crate-level attributes of
8 //! `#![feature(...)]` with a comma-separated list of features.
9 //!
10 //! For the purpose of future feature-tracking, once a feature gate is added,
11 //! even if it is stabilized or removed, *do not remove it*. Instead, move the
12 //! symbol to the `accepted` or `removed` modules respectively.
13
14 mod accepted;
15 mod active;
16 mod builtin_attrs;
17 mod removed;
18
19 use rustc_span::{edition::Edition, symbol::Symbol, Span};
20 use std::fmt;
21 use std::num::NonZeroU32;
22
23 #[derive(Clone, Copy)]
24 pub enum State {
25     Accepted,
26     Active { set: fn(&mut Features, Span) },
27     Removed { reason: Option<&'static str> },
28     Stabilized { reason: Option<&'static str> },
29 }
30
31 impl fmt::Debug for State {
32     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33         match self {
34             State::Accepted { .. } => write!(f, "accepted"),
35             State::Active { .. } => write!(f, "active"),
36             State::Removed { .. } => write!(f, "removed"),
37             State::Stabilized { .. } => write!(f, "stabilized"),
38         }
39     }
40 }
41
42 #[derive(Debug, Clone)]
43 pub struct Feature {
44     pub state: State,
45     pub name: Symbol,
46     pub since: &'static str,
47     issue: Option<u32>, // FIXME: once #58732 is done make this an Option<NonZeroU32>
48     pub edition: Option<Edition>,
49     description: &'static str,
50 }
51
52 impl Feature {
53     fn issue(&self) -> Option<NonZeroU32> {
54         self.issue.and_then(|i| NonZeroU32::new(i))
55     }
56 }
57
58 #[derive(Copy, Clone, Debug)]
59 pub enum Stability {
60     Unstable,
61     // First argument is tracking issue link; second argument is an optional
62     // help message, which defaults to "remove this attribute".
63     Deprecated(&'static str, Option<&'static str>),
64 }
65
66 #[derive(Clone, Copy, Hash)]
67 pub enum UnstableFeatures {
68     /// Hard errors for unstable features are active, as on beta/stable channels.
69     Disallow,
70     /// Allow features to be activated, as on nightly.
71     Allow,
72     /// Errors are bypassed for bootstrapping. This is required any time
73     /// during the build that feature-related lints are set to warn or above
74     /// because the build turns on warnings-as-errors and uses lots of unstable
75     /// features. As a result, this is always required for building Rust itself.
76     Cheat,
77 }
78
79 impl UnstableFeatures {
80     pub fn from_environment() -> UnstableFeatures {
81         // `true` if this is a feature-staged build, i.e., on the beta or stable channel.
82         let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
83         // `true` if we should enable unstable features for bootstrapping.
84         let bootstrap = std::env::var("RUSTC_BOOTSTRAP").is_ok();
85         match (disable_unstable_features, bootstrap) {
86             (_, true) => UnstableFeatures::Cheat,
87             (true, _) => UnstableFeatures::Disallow,
88             (false, _) => UnstableFeatures::Allow,
89         }
90     }
91
92     pub fn is_nightly_build(&self) -> bool {
93         match *self {
94             UnstableFeatures::Allow | UnstableFeatures::Cheat => true,
95             UnstableFeatures::Disallow => false,
96         }
97     }
98 }
99
100 fn find_lang_feature_issue(feature: Symbol) -> Option<NonZeroU32> {
101     if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.name == feature) {
102         // FIXME (#28244): enforce that active features have issue numbers
103         // assert!(info.issue().is_some())
104         info.issue()
105     } else {
106         // search in Accepted, Removed, or Stable Removed features
107         let found = ACCEPTED_FEATURES
108             .iter()
109             .chain(REMOVED_FEATURES)
110             .chain(STABLE_REMOVED_FEATURES)
111             .find(|t| t.name == feature);
112         match found {
113             Some(found) => found.issue(),
114             None => panic!("feature `{}` is not declared anywhere", feature),
115         }
116     }
117 }
118
119 pub enum GateIssue {
120     Language,
121     Library(Option<NonZeroU32>),
122 }
123
124 pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZeroU32> {
125     match issue {
126         GateIssue::Language => find_lang_feature_issue(feature),
127         GateIssue::Library(lib) => lib,
128     }
129 }
130
131 pub use accepted::ACCEPTED_FEATURES;
132 pub use active::{Features, ACTIVE_FEATURES, INCOMPLETE_FEATURES};
133 pub use builtin_attrs::{
134     deprecated_attributes, find_gated_cfg, is_builtin_attr_name, AttributeGate, AttributeTemplate,
135     AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
136 };
137 pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};