Skip to content

Commit 8825942

Browse files
Rollup merge of #77802 - jyn514:bootstrap-specific, r=nikomatsakis
Allow making `RUSTC_BOOTSTRAP` conditional on the crate name Motivation: This came up in the [Zulip stream](https://rust-lang.zulipchat.com/#narrow/stream/233931-t-compiler.2Fmajor-changes/topic/Require.20users.20to.20confirm.20they.20know.20RUSTC_.E2.80.A6.20compiler-team.23350/near/208403962) for rust-lang/compiler-team#350. See also rust-lang/cargo#6608 (comment); this implements rust-lang/cargo#6627. The goal is for this to eventually allow prohibiting setting `RUSTC_BOOTSTRAP` in build.rs (rust-lang/cargo#7088). ## User-facing changes - `RUSTC_BOOTSTRAP=1` still works; there is no current plan to remove this. - Things like `RUSTC_BOOTSTRAP=0` no longer activate nightly features. In practice this shouldn't be a big deal, since `RUSTC_BOOTSTRAP` is the opposite of stable and everyone uses `RUSTC_BOOTSTRAP=1` anyway. - `RUSTC_BOOTSTRAP=x` will enable nightly features only for crate `x`. - `RUSTC_BOOTSTRAP=x,y` will enable nightly features only for crates `x` and `y`. ## Implementation changes The main change is that `UnstableOptions::from_environment` now requires an (optional) crate name. If the crate name is unknown (`None`), then the new feature is not available and you still have to use `RUSTC_BOOTSTRAP=1`. In practice this means the feature is only available for `--crate-name`, not for `#![crate_name]`; I'm interested in supporting the second but I'm not sure how. Other major changes: - Added `Session::is_nightly_build()`, which uses the `crate_name` of the session - Added `nightly_options::match_is_nightly_build`, a convenience method for looking up `--crate-name` from CLI arguments. `Session::is_nightly_build()`should be preferred where possible, since it will take into account `#![crate_name]` (I think). - Added `unstable_features` to `rustdoc::RenderOptions` I'm not sure whether this counts as T-compiler or T-lang; _technically_ RUSTC_BOOTSTRAP is an implementation detail, but it's been used so much it seems like this counts as a language change too. r? `@joshtriplett` cc `@Mark-Simulacrum` `@hsivonen`
2 parents 7504256 + 622c48e commit 8825942

File tree

26 files changed

+128
-80
lines changed

26 files changed

+128
-80
lines changed

compiler/rustc_ast_lowering/src/lib.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ use rustc_hir::definitions::{DefKey, DefPathData, Definitions};
5353
use rustc_hir::intravisit;
5454
use rustc_hir::{ConstArg, GenericArg, ParamName};
5555
use rustc_index::vec::{Idx, IndexVec};
56-
use rustc_session::config::nightly_options;
5756
use rustc_session::lint::{builtin::BARE_TRAIT_OBJECTS, BuiltinLintDiagnostics, LintBuffer};
5857
use rustc_session::parse::ParseSess;
5958
use rustc_session::Session;
@@ -1398,8 +1397,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
13981397
"`impl Trait` not allowed outside of {}",
13991398
allowed_in,
14001399
);
1401-
if pos == ImplTraitPosition::Binding && nightly_options::is_nightly_build()
1402-
{
1400+
if pos == ImplTraitPosition::Binding && self.sess.is_nightly_build() {
14031401
err.help(
14041402
"add `#![feature(impl_trait_in_bindings)]` to the crate \
14051403
attributes to enable",

compiler/rustc_codegen_llvm/src/llvm_util.rs

+5-8
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ use crate::llvm;
33
use libc::c_int;
44
use rustc_codegen_ssa::target_features::supported_target_features;
55
use rustc_data_structures::fx::FxHashSet;
6-
use rustc_feature::UnstableFeatures;
76
use rustc_middle::bug;
87
use rustc_session::config::PrintRequest;
98
use rustc_session::Session;
@@ -147,13 +146,11 @@ pub fn target_features(sess: &Session) -> Vec<Symbol> {
147146
let target_machine = create_informational_target_machine(sess);
148147
supported_target_features(sess)
149148
.iter()
150-
.filter_map(|&(feature, gate)| {
151-
if UnstableFeatures::from_environment().is_nightly_build() || gate.is_none() {
152-
Some(feature)
153-
} else {
154-
None
155-
}
156-
})
149+
.filter_map(
150+
|&(feature, gate)| {
151+
if sess.is_nightly_build() || gate.is_none() { Some(feature) } else { None }
152+
},
153+
)
157154
.filter(|feature| {
158155
let llvm_feature = to_llvm_feature(sess, feature);
159156
let cstr = CString::new(llvm_feature).unwrap();

compiler/rustc_driver/src/lib.rs

+11-10
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use rustc_data_structures::profiling::print_time_passes_entry;
2020
use rustc_data_structures::sync::SeqCst;
2121
use rustc_errors::registry::{InvalidErrorCode, Registry};
2222
use rustc_errors::{ErrorReported, PResult};
23-
use rustc_feature::{find_gated_cfg, UnstableFeatures};
23+
use rustc_feature::find_gated_cfg;
2424
use rustc_hir::def_id::LOCAL_CRATE;
2525
use rustc_interface::util::{self, collect_crate_types, get_builtin_codegen_backend};
2626
use rustc_interface::{interface, Queries};
@@ -746,9 +746,6 @@ impl RustcDefaultCalls {
746746
}
747747
}
748748
Cfg => {
749-
let allow_unstable_cfg =
750-
UnstableFeatures::from_environment().is_nightly_build();
751-
752749
let mut cfgs = sess
753750
.parse_sess
754751
.config
@@ -763,7 +760,7 @@ impl RustcDefaultCalls {
763760
// it, this is intended to get into Cargo and then go
764761
// through to build scripts.
765762
if (name != sym::target_feature || value != Some(sym::crt_dash_static))
766-
&& !allow_unstable_cfg
763+
&& !sess.is_nightly_build()
767764
&& find_gated_cfg(|cfg_sym| cfg_sym == name).is_some()
768765
{
769766
return None;
@@ -814,14 +811,14 @@ pub fn version(binary: &str, matches: &getopts::Matches) {
814811
}
815812
}
816813

817-
fn usage(verbose: bool, include_unstable_options: bool) {
814+
fn usage(verbose: bool, include_unstable_options: bool, nightly_build: bool) {
818815
let groups = if verbose { config::rustc_optgroups() } else { config::rustc_short_optgroups() };
819816
let mut options = getopts::Options::new();
820817
for option in groups.iter().filter(|x| include_unstable_options || x.is_stable()) {
821818
(option.apply)(&mut options);
822819
}
823820
let message = "Usage: rustc [OPTIONS] INPUT";
824-
let nightly_help = if nightly_options::is_nightly_build() {
821+
let nightly_help = if nightly_build {
825822
"\n -Z help Print unstable compiler options"
826823
} else {
827824
""
@@ -831,7 +828,7 @@ fn usage(verbose: bool, include_unstable_options: bool) {
831828
} else {
832829
"\n --help -v Print the full set of options rustc accepts"
833830
};
834-
let at_path = if verbose && nightly_options::is_nightly_build() {
831+
let at_path = if verbose && nightly_build {
835832
" @path Read newline separated options from `path`\n"
836833
} else {
837834
""
@@ -1034,7 +1031,9 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
10341031
if args.is_empty() {
10351032
// user did not write `-v` nor `-Z unstable-options`, so do not
10361033
// include that extra information.
1037-
usage(false, false);
1034+
let nightly_build =
1035+
rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build();
1036+
usage(false, false, nightly_build);
10381037
return None;
10391038
}
10401039

@@ -1063,7 +1062,9 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
10631062

10641063
if matches.opt_present("h") || matches.opt_present("help") {
10651064
// Only show unstable options in --help if we accept unstable options.
1066-
usage(matches.opt_present("verbose"), nightly_options::is_unstable_enabled(&matches));
1065+
let unstable_enabled = nightly_options::is_unstable_enabled(&matches);
1066+
let nightly_build = nightly_options::match_is_nightly_build(&matches);
1067+
usage(matches.opt_present("verbose"), unstable_enabled, nightly_build);
10671068
return None;
10681069
}
10691070

compiler/rustc_feature/src/lib.rs

+39-3
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ pub enum Stability {
5959
Deprecated(&'static str, Option<&'static str>),
6060
}
6161

62-
#[derive(Clone, Copy, Hash)]
62+
#[derive(Clone, Copy, Debug, Hash)]
6363
pub enum UnstableFeatures {
6464
/// Hard errors for unstable features are active, as on beta/stable channels.
6565
Disallow,
@@ -73,11 +73,20 @@ pub enum UnstableFeatures {
7373
}
7474

7575
impl UnstableFeatures {
76-
pub fn from_environment() -> UnstableFeatures {
76+
/// This takes into account `RUSTC_BOOTSTRAP`.
77+
///
78+
/// If `krate` is [`Some`], then setting `RUSTC_BOOTSTRAP=krate` will enable the nightly features.
79+
/// Otherwise, only `RUSTC_BOOTSTRAP=1` will work.
80+
pub fn from_environment(krate: Option<&str>) -> Self {
7781
// `true` if this is a feature-staged build, i.e., on the beta or stable channel.
7882
let disable_unstable_features = option_env!("CFG_DISABLE_UNSTABLE_FEATURES").is_some();
83+
// Returns whether `krate` should be counted as unstable
84+
let is_unstable_crate = |var: &str| {
85+
krate.map_or(false, |name| var.split(',').any(|new_krate| new_krate == name))
86+
};
7987
// `true` if we should enable unstable features for bootstrapping.
80-
let bootstrap = std::env::var("RUSTC_BOOTSTRAP").is_ok();
88+
let bootstrap = std::env::var("RUSTC_BOOTSTRAP")
89+
.map_or(false, |var| var == "1" || is_unstable_crate(&var));
8190
match (disable_unstable_features, bootstrap) {
8291
(_, true) => UnstableFeatures::Cheat,
8392
(true, _) => UnstableFeatures::Disallow,
@@ -140,3 +149,30 @@ pub use builtin_attrs::{
140149
AttributeType, BuiltinAttribute, GatedCfg, BUILTIN_ATTRIBUTES, BUILTIN_ATTRIBUTE_MAP,
141150
};
142151
pub use removed::{REMOVED_FEATURES, STABLE_REMOVED_FEATURES};
152+
153+
#[cfg(test)]
154+
mod test {
155+
use super::UnstableFeatures;
156+
157+
#[test]
158+
fn rustc_bootstrap_parsing() {
159+
let is_bootstrap = |env, krate| {
160+
std::env::set_var("RUSTC_BOOTSTRAP", env);
161+
matches!(UnstableFeatures::from_environment(krate), UnstableFeatures::Cheat)
162+
};
163+
assert!(is_bootstrap("1", None));
164+
assert!(is_bootstrap("1", Some("x")));
165+
// RUSTC_BOOTSTRAP allows specifying a specific crate
166+
assert!(is_bootstrap("x", Some("x")));
167+
// RUSTC_BOOTSTRAP allows multiple comma-delimited crates
168+
assert!(is_bootstrap("x,y,z", Some("x")));
169+
assert!(is_bootstrap("x,y,z", Some("y")));
170+
// Crate that aren't specified do not get unstable features
171+
assert!(!is_bootstrap("x", Some("a")));
172+
assert!(!is_bootstrap("x,y,z", Some("a")));
173+
assert!(!is_bootstrap("x,y,z", None));
174+
175+
// this is technically a breaking change, but there are no stability guarantees for RUSTC_BOOTSTRAP
176+
assert!(!is_bootstrap("0", None));
177+
}
178+
}

compiler/rustc_incremental/src/persist/file_format.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use std::io::{self, Read};
1515
use std::path::Path;
1616

1717
use rustc_serialize::opaque::Encoder;
18-
use rustc_session::config::nightly_options;
1918

2019
/// The first few bytes of files generated by incremental compilation.
2120
const FILE_MAGIC: &[u8] = b"RSIC";
@@ -28,12 +27,12 @@ const HEADER_FORMAT_VERSION: u16 = 0;
2827
/// the Git commit hash.
2928
const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
3029

31-
pub fn write_file_header(stream: &mut Encoder) {
30+
pub fn write_file_header(stream: &mut Encoder, nightly_build: bool) {
3231
stream.emit_raw_bytes(FILE_MAGIC);
3332
stream
3433
.emit_raw_bytes(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8]);
3534

36-
let rustc_version = rustc_version();
35+
let rustc_version = rustc_version(nightly_build);
3736
assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize);
3837
stream.emit_raw_bytes(&[rustc_version.len() as u8]);
3938
stream.emit_raw_bytes(rustc_version.as_bytes());
@@ -51,6 +50,7 @@ pub fn write_file_header(stream: &mut Encoder) {
5150
pub fn read_file(
5251
report_incremental_info: bool,
5352
path: &Path,
53+
nightly_build: bool,
5454
) -> io::Result<Option<(Vec<u8>, usize)>> {
5555
if !path.exists() {
5656
return Ok(None);
@@ -93,7 +93,7 @@ pub fn read_file(
9393
let mut buffer = vec![0; rustc_version_str_len];
9494
file.read_exact(&mut buffer)?;
9595

96-
if buffer != rustc_version().as_bytes() {
96+
if buffer != rustc_version(nightly_build).as_bytes() {
9797
report_format_mismatch(report_incremental_info, path, "Different compiler version");
9898
return Ok(None);
9999
}
@@ -115,8 +115,8 @@ fn report_format_mismatch(report_incremental_info: bool, file: &Path, message: &
115115
}
116116
}
117117

118-
fn rustc_version() -> String {
119-
if nightly_options::is_nightly_build() {
118+
fn rustc_version(nightly_build: bool) -> String {
119+
if nightly_build {
120120
if let Some(val) = env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") {
121121
return val.to_string_lossy().into_owned();
122122
}

compiler/rustc_incremental/src/persist/load.rs

+14-5
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,12 @@ impl LoadResult<(PreviousDepGraph, WorkProductMap)> {
5353
}
5454
}
5555

56-
fn load_data(report_incremental_info: bool, path: &Path) -> LoadResult<(Vec<u8>, usize)> {
57-
match file_format::read_file(report_incremental_info, path) {
56+
fn load_data(
57+
report_incremental_info: bool,
58+
path: &Path,
59+
nightly_build: bool,
60+
) -> LoadResult<(Vec<u8>, usize)> {
61+
match file_format::read_file(report_incremental_info, path, nightly_build) {
5862
Ok(Some(data_and_pos)) => LoadResult::Ok { data: data_and_pos },
5963
Ok(None) => {
6064
// The file either didn't exist or was produced by an incompatible
@@ -111,13 +115,14 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
111115
let expected_hash = sess.opts.dep_tracking_hash();
112116

113117
let mut prev_work_products = FxHashMap::default();
118+
let nightly_build = sess.is_nightly_build();
114119

115120
// If we are only building with -Zquery-dep-graph but without an actual
116121
// incr. comp. session directory, we skip this. Otherwise we'd fail
117122
// when trying to load work products.
118123
if sess.incr_comp_session_dir_opt().is_some() {
119124
let work_products_path = work_products_path(sess);
120-
let load_result = load_data(report_incremental_info, &work_products_path);
125+
let load_result = load_data(report_incremental_info, &work_products_path, nightly_build);
121126

122127
if let LoadResult::Ok { data: (work_products_data, start_pos) } = load_result {
123128
// Decode the list of work_products
@@ -163,7 +168,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture {
163168
MaybeAsync::Async(std::thread::spawn(move || {
164169
let _prof_timer = prof.generic_activity("incr_comp_load_dep_graph");
165170

166-
match load_data(report_incremental_info, &path) {
171+
match load_data(report_incremental_info, &path, nightly_build) {
167172
LoadResult::DataOutOfDate => LoadResult::DataOutOfDate,
168173
LoadResult::Error { message } => LoadResult::Error { message },
169174
LoadResult::Ok { data: (bytes, start_pos) } => {
@@ -201,7 +206,11 @@ pub fn load_query_result_cache(sess: &Session) -> OnDiskCache<'_> {
201206

202207
let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache");
203208

204-
match load_data(sess.opts.debugging_opts.incremental_info, &query_cache_path(sess)) {
209+
match load_data(
210+
sess.opts.debugging_opts.incremental_info,
211+
&query_cache_path(sess),
212+
sess.is_nightly_build(),
213+
) {
205214
LoadResult::Ok { data: (bytes, start_pos) } => OnDiskCache::new(sess, bytes, start_pos),
206215
_ => OnDiskCache::new_empty(sess.source_map()),
207216
}

compiler/rustc_incremental/src/persist/save.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ where
119119

120120
// generate the data in a memory buffer
121121
let mut encoder = Encoder::new(Vec::new());
122-
file_format::write_file_header(&mut encoder);
122+
file_format::write_file_header(&mut encoder, sess.is_nightly_build());
123123
encode(&mut encoder);
124124

125125
// write the data out

compiler/rustc_mir/src/transform/check_consts/ops.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ use rustc_errors::{struct_span_err, DiagnosticBuilder};
44
use rustc_hir as hir;
55
use rustc_hir::def_id::DefId;
66
use rustc_middle::mir;
7-
use rustc_session::config::nightly_options;
87
use rustc_session::parse::feature_err;
98
use rustc_span::symbol::sym;
109
use rustc_span::{Span, Symbol};
@@ -104,7 +103,7 @@ impl NonConstOp for FnCallUnstable {
104103

105104
if ccx.is_const_stable_const_fn() {
106105
err.help("Const-stable functions can only call other const-stable functions");
107-
} else if nightly_options::is_nightly_build() {
106+
} else if ccx.tcx.sess.is_nightly_build() {
108107
if let Some(feature) = feature {
109108
err.help(&format!(
110109
"add `#![feature({})]` to the crate attributes to enable",

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use rustc_hir::def_id::DefId;
1212
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
1313
use rustc_hir::{HirId, Pat};
1414
use rustc_middle::ty::{self, Ty, TyCtxt};
15-
use rustc_session::config::nightly_options;
1615
use rustc_session::lint::builtin::BINDINGS_WITH_VARIANT_NAME;
1716
use rustc_session::lint::builtin::{IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS};
1817
use rustc_session::parse::feature_err;
@@ -502,7 +501,7 @@ fn check_exhaustive<'p, 'tcx>(
502501
so a wildcard `_` is necessary to match exhaustively",
503502
scrut_ty,
504503
));
505-
if nightly_options::is_nightly_build() {
504+
if cx.tcx.sess.is_nightly_build() {
506505
err.help(&format!(
507506
"add `#![feature(precise_pointer_size_matching)]` \
508507
to the crate attributes to enable precise `{}` matching",

compiler/rustc_passes/src/check_const.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
1515
use rustc_middle::hir::map::Map;
1616
use rustc_middle::ty::query::Providers;
1717
use rustc_middle::ty::TyCtxt;
18-
use rustc_session::config::nightly_options;
1918
use rustc_session::parse::feature_err;
2019
use rustc_span::{sym, Span, Symbol};
2120

@@ -145,7 +144,7 @@ impl<'tcx> CheckConstVisitor<'tcx> {
145144
//
146145
// FIXME(ecstaticmorse): Maybe this could be incorporated into `feature_err`? This
147146
// is a pretty narrow case, however.
148-
if nightly_options::is_nightly_build() {
147+
if tcx.sess.is_nightly_build() {
149148
for gate in missing_secondary {
150149
let note = format!(
151150
"add `#![feature({})]` to the crate attributes to enable",

compiler/rustc_resolve/src/late/diagnostics.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc_hir::def::Namespace::{self, *};
1616
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind};
1717
use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
1818
use rustc_hir::PrimTy;
19-
use rustc_session::config::nightly_options;
2019
use rustc_session::parse::feature_err;
2120
use rustc_span::hygiene::MacroKind;
2221
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -890,7 +889,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
890889
}
891890
(Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
892891
err.span_label(span, "type aliases cannot be used as traits");
893-
if nightly_options::is_nightly_build() {
892+
if self.r.session.is_nightly_build() {
894893
let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
895894
`type` alias";
896895
if let Some(span) = self.def_span(def_id) {
@@ -1675,7 +1674,7 @@ impl<'tcx> LifetimeContext<'_, 'tcx> {
16751674
_ => {}
16761675
}
16771676
}
1678-
if nightly_options::is_nightly_build()
1677+
if self.tcx.sess.is_nightly_build()
16791678
&& !self.tcx.features().in_band_lifetimes
16801679
&& suggests_in_band
16811680
{

0 commit comments

Comments
 (0)