@@ -64,38 +64,52 @@ pub enum UnstableFeatures {
6464}
6565
6666impl UnstableFeatures {
67- /// This takes into account `RUSTC_BOOTSTRAP`.
68- ///
69- /// If `krate` is [`Some`], then setting `RUSTC_BOOTSTRAP=krate` will enable the nightly
70- /// features. Otherwise, only `RUSTC_BOOTSTRAP=1` will work.
71- pub fn from_environment ( krate : Option < & str > ) -> Self {
72- Self :: from_environment_inner ( krate , |name| env:: var ( name) )
67+ /// Determines whether this compiler allows unstable options/features,
68+ /// according to whether it was built as a stable/beta compiler or a nightly
69+ /// compiler, and taking `RUSTC_BOOTSTRAP` into account.
70+ # [ inline ( never ) ]
71+ pub fn from_environment ( ) -> Self {
72+ Self :: from_environment_inner ( |name| env:: var ( name) )
7373 }
7474
7575 /// Unit tests can pass a mock `std::env::var` instead of modifying the real environment.
7676 fn from_environment_inner (
77- krate : Option < & str > ,
7877 env_var : impl Fn ( & str ) -> Result < String , env:: VarError > , // std::env::var
7978 ) -> Self {
80- // `true` if this is a feature-staged build, i.e., on the beta or stable channel.
79+ // If `CFG_DISABLE_UNSTABLE_FEATURES` was true when this compiler was
80+ // built, it is a stable/beta compiler that forbids unstable features.
8181 let disable_unstable_features =
8282 option_env ! ( "CFG_DISABLE_UNSTABLE_FEATURES" ) . is_some_and ( |s| s != "0" ) ;
83- // Returns whether `krate` should be counted as unstable
84- 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- // Hypnotize ourselves so that we think we are a stable compiler and thus don't
92- // allow any unstable features.
93- "-1" => return UnstableFeatures :: Disallow ,
94- _ => { }
95- }
83+ let default_answer = if disable_unstable_features {
84+ UnstableFeatures :: Disallow
85+ } else {
86+ UnstableFeatures :: Allow
87+ } ;
88+
89+ // Returns true if the given list of comma-separated crate names
90+ // contains `CARGO_CRATE_NAME`.
91+ //
92+ // This is not actually used by bootstrap; it only exists so that when
93+ // cargo sees a third-party crate trying to set `RUSTC_BOOTSTRAP=1` in
94+ // build.rs, it can suggest a somewhat less horrifying alternative.
95+ //
96+ // See <https://github.com/rust-lang/rust/pull/77802> for context.
97+ let includes_current_crate = |names : & str | -> bool {
98+ let Ok ( crate_name) = env_var ( "CARGO_CRATE_NAME" ) else { return false } ;
99+ // Normalize `-` in crate names to `_`.
100+ let crate_name = crate_name. replace ( '-' , "_" ) ;
101+ names. replace ( '-' , "_" ) . split ( ',' ) . any ( |name| name == crate_name)
102+ } ;
103+
104+ match env_var ( "RUSTC_BOOTSTRAP" ) . as_deref ( ) {
105+ // Force the compiler to act as nightly, even if it's stable.
106+ Ok ( "1" ) => UnstableFeatures :: Cheat ,
107+ // Force the compiler to act as stable, even if it's nightly.
108+ Ok ( "-1" ) => UnstableFeatures :: Disallow ,
109+ // Force nightly if `RUSTC_BOOTSTRAP` contains the current crate name.
110+ Ok ( names) if includes_current_crate ( names) => UnstableFeatures :: Cheat ,
111+ _ => default_answer,
96112 }
97-
98- if disable_unstable_features { UnstableFeatures :: Disallow } else { UnstableFeatures :: Allow }
99113 }
100114
101115 pub fn is_nightly_build ( & self ) -> bool {
0 commit comments