Skip to content

Commit b219f0e

Browse files
committed
Auto merge of #9181 - jyn514:computer-says-no, r=ehuss
Forbid setting `RUSTC_BOOTSTRAP` from a build script on stable Instead, recommend `RUSTC_BOOTSTRAP=crate_name`. If cargo is using a nightly toolchain, or if RUSTC_BOOTSTRAP was set in *cargo*'s build environment, the error is downgraded to a warning, since the variable won't affect the build. This is mostly the same as suggested in #7088 (comment), except that `RUSTC_BOOTSTRAP=` values other than 1 are treated the same as `RUSTC_BOOTSTRAP=1`. My reasoning was that rust-lang/rust#77802 is now on 1.50 stable, so some crates may have started using it, and I would still prefer not to give hard errors when there's no workaround. Closes #7088. r? `@joshtriplett`
2 parents c68432f + 0b18165 commit b219f0e

File tree

16 files changed

+174
-114
lines changed

16 files changed

+174
-114
lines changed

crates/resolver-tests/tests/resolve.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use cargo::core::dependency::DepKind;
2-
use cargo::core::{enable_nightly_features, Dependency};
2+
use cargo::core::Dependency;
33
use cargo::util::{is_ci, Config};
44

55
use resolver_tests::{
@@ -55,9 +55,8 @@ proptest! {
5555
fn prop_minimum_version_errors_the_same(
5656
PrettyPrintRegistry(input) in registry_strategy(50, 20, 60)
5757
) {
58-
enable_nightly_features();
59-
6058
let mut config = Config::default().unwrap();
59+
config.nightly_features_allowed = true;
6160
config
6261
.configure(
6362
1,
@@ -553,11 +552,6 @@ fn test_resolving_maximum_version_with_transitive_deps() {
553552

554553
#[test]
555554
fn test_resolving_minimum_version_with_transitive_deps() {
556-
enable_nightly_features(); // -Z minimal-versions
557-
// When the minimal-versions config option is specified then the lowest
558-
// possible version of a package should be selected. "util 1.0.0" can't be
559-
// selected because of the requirements of "bar", so the minimum version
560-
// must be 1.1.1.
561555
let reg = registry(vec![
562556
pkg!(("util", "1.2.2")),
563557
pkg!(("util", "1.0.0")),
@@ -567,6 +561,12 @@ fn test_resolving_minimum_version_with_transitive_deps() {
567561
]);
568562

569563
let mut config = Config::default().unwrap();
564+
// -Z minimal-versions
565+
// When the minimal-versions config option is specified then the lowest
566+
// possible version of a package should be selected. "util 1.0.0" can't be
567+
// selected because of the requirements of "bar", so the minimum version
568+
// must be 1.1.1.
569+
config.nightly_features_allowed = true;
570570
config
571571
.configure(
572572
1,

src/bin/cargo/cli.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ Available unstable (nightly-only) flags:
4848
4949
Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
5050
);
51-
if !features::nightly_features_allowed() {
51+
if !config.nightly_features_allowed {
5252
drop_println!(
5353
config,
5454
"\nUnstable flags are only available on the nightly channel \

src/bin/cargo/commands/logout.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub fn exec(config: &mut Config, args: &ArgMatches<'_>) -> CliResult {
1616
if !(unstable.credential_process || unstable.unstable_options) {
1717
const SEE: &str = "See https://github.com/rust-lang/cargo/issues/8933 for more \
1818
information about the `cargo logout` command.";
19-
if features::nightly_features_allowed() {
19+
if config.nightly_features_allowed {
2020
return Err(format_err!(
2121
"the `cargo logout` command is unstable, pass `-Z unstable-options` to enable it\n\
2222
{}",

src/bin/cargo/main.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ fn main() {
2222
pretty_env_logger::init_custom_env("CARGO_LOG");
2323
#[cfg(not(feature = "pretty-env-logger"))]
2424
env_logger::init_from_env("CARGO_LOG");
25-
cargo::core::maybe_allow_nightly_features();
2625

2726
let mut config = match Config::default() {
2827
Ok(cfg) => cfg,
@@ -32,7 +31,7 @@ fn main() {
3231
}
3332
};
3433

35-
let result = match cargo::ops::fix_maybe_exec_rustc() {
34+
let result = match cargo::ops::fix_maybe_exec_rustc(&config) {
3635
Ok(true) => Ok(()),
3736
Ok(false) => {
3837
let _token = cargo::util::job::setup();

src/cargo/core/compiler/custom_build.rs

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::core::compiler::context::Metadata;
44
use crate::core::compiler::job_queue::JobState;
55
use crate::core::{profiles::ProfileRoot, PackageId};
66
use crate::util::errors::{CargoResult, CargoResultExt};
7+
use crate::util::interning::InternedString;
78
use crate::util::machine_message::{self, Message};
89
use crate::util::{self, internal, paths, profile};
910
use cargo_platform::Cfg;
@@ -267,7 +268,8 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
267268
}
268269
})
269270
.collect::<Vec<_>>();
270-
let pkg_name = unit.pkg.to_string();
271+
let pkg_name = unit.pkg.name();
272+
let pkg_descr = unit.pkg.to_string();
271273
let build_script_outputs = Arc::clone(&cx.build_script_outputs);
272274
let id = unit.pkg.package_id();
273275
let output_file = script_run_dir.join("output");
@@ -276,7 +278,8 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
276278
let host_target_root = cx.files().host_dest().to_path_buf();
277279
let all = (
278280
id,
279-
pkg_name.clone(),
281+
pkg_name,
282+
pkg_descr.clone(),
280283
Arc::clone(&build_script_outputs),
281284
output_file.clone(),
282285
script_out_dir.clone(),
@@ -291,6 +294,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
291294
paths::create_dir_all(&script_out_dir)?;
292295

293296
let extra_link_arg = cx.bcx.config.cli_unstable().extra_link_arg;
297+
let nightly_features_allowed = cx.bcx.config.nightly_features_allowed;
294298

295299
// Prepare the unit of "dirty work" which will actually run the custom build
296300
// command.
@@ -365,7 +369,7 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
365369
},
366370
true,
367371
)
368-
.chain_err(|| format!("failed to run custom build command for `{}`", pkg_name));
372+
.chain_err(|| format!("failed to run custom build command for `{}`", pkg_descr));
369373

370374
if let Err(error) = output {
371375
insert_warnings_in_build_outputs(
@@ -394,10 +398,12 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
394398
paths::write(&root_output_file, util::path2bytes(&script_out_dir)?)?;
395399
let parsed_output = BuildOutput::parse(
396400
&output.stdout,
397-
&pkg_name,
401+
pkg_name,
402+
&pkg_descr,
398403
&script_out_dir,
399404
&script_out_dir,
400405
extra_link_arg,
406+
nightly_features_allowed,
401407
)?;
402408

403409
if json_messages {
@@ -414,15 +420,17 @@ fn build_work(cx: &mut Context<'_, '_>, unit: &Unit) -> CargoResult<Job> {
414420
// itself to run when we actually end up just discarding what we calculated
415421
// above.
416422
let fresh = Work::new(move |state| {
417-
let (id, pkg_name, build_script_outputs, output_file, script_out_dir) = all;
423+
let (id, pkg_name, pkg_descr, build_script_outputs, output_file, script_out_dir) = all;
418424
let output = match prev_output {
419425
Some(output) => output,
420426
None => BuildOutput::parse_file(
421427
&output_file,
422-
&pkg_name,
428+
pkg_name,
429+
&pkg_descr,
423430
&prev_script_out_dir,
424431
&script_out_dir,
425432
extra_link_arg,
433+
nightly_features_allowed,
426434
)?,
427435
};
428436

@@ -469,29 +477,35 @@ fn insert_warnings_in_build_outputs(
469477
impl BuildOutput {
470478
pub fn parse_file(
471479
path: &Path,
472-
pkg_name: &str,
480+
pkg_name: InternedString,
481+
pkg_descr: &str,
473482
script_out_dir_when_generated: &Path,
474483
script_out_dir: &Path,
475484
extra_link_arg: bool,
485+
nightly_features_allowed: bool,
476486
) -> CargoResult<BuildOutput> {
477487
let contents = paths::read_bytes(path)?;
478488
BuildOutput::parse(
479489
&contents,
480490
pkg_name,
491+
pkg_descr,
481492
script_out_dir_when_generated,
482493
script_out_dir,
483494
extra_link_arg,
495+
nightly_features_allowed,
484496
)
485497
}
486498

487499
// Parses the output of a script.
488500
// The `pkg_name` is used for error messages.
489501
pub fn parse(
490502
input: &[u8],
491-
pkg_name: &str,
503+
pkg_name: InternedString,
504+
pkg_descr: &str,
492505
script_out_dir_when_generated: &Path,
493506
script_out_dir: &Path,
494507
extra_link_arg: bool,
508+
nightly_features_allowed: bool,
495509
) -> CargoResult<BuildOutput> {
496510
let mut library_paths = Vec::new();
497511
let mut library_links = Vec::new();
@@ -502,7 +516,7 @@ impl BuildOutput {
502516
let mut rerun_if_changed = Vec::new();
503517
let mut rerun_if_env_changed = Vec::new();
504518
let mut warnings = Vec::new();
505-
let whence = format!("build script of `{}`", pkg_name);
519+
let whence = format!("build script of `{}`", pkg_descr);
506520

507521
for line in input.split(|b| *b == b'\n') {
508522
let line = match str::from_utf8(line) {
@@ -562,7 +576,37 @@ impl BuildOutput {
562576
}
563577
}
564578
"rustc-cfg" => cfgs.push(value.to_string()),
565-
"rustc-env" => env.push(BuildOutput::parse_rustc_env(&value, &whence)?),
579+
"rustc-env" => {
580+
let (key, val) = BuildOutput::parse_rustc_env(&value, &whence)?;
581+
// Build scripts aren't allowed to set RUSTC_BOOTSTRAP.
582+
// See https://github.com/rust-lang/cargo/issues/7088.
583+
if key == "RUSTC_BOOTSTRAP" {
584+
// If RUSTC_BOOTSTRAP is already set, the user of Cargo knows about
585+
// bootstrap and still wants to override the channel. Give them a way to do
586+
// so, but still emit a warning that the current crate shouldn't be trying
587+
// to set RUSTC_BOOTSTRAP.
588+
// If this is a nightly build, setting RUSTC_BOOTSTRAP wouldn't affect the
589+
// behavior, so still only give a warning.
590+
if nightly_features_allowed {
591+
warnings.push(format!("Cannot set `RUSTC_BOOTSTRAP={}` from {}.\n\
592+
note: Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.",
593+
val, whence
594+
));
595+
} else {
596+
// Setting RUSTC_BOOTSTRAP would change the behavior of the crate.
597+
// Abort with an error.
598+
anyhow::bail!("Cannot set `RUSTC_BOOTSTRAP={}` from {}.\n\
599+
note: Crates cannot set `RUSTC_BOOTSTRAP` themselves, as doing so would subvert the stability guarantees of Rust for your project.\n\
600+
help: If you're sure you want to do this in your project, set the environment variable `RUSTC_BOOTSTRAP={}` before running cargo instead.",
601+
val,
602+
whence,
603+
pkg_name,
604+
);
605+
}
606+
} else {
607+
env.push((key, val));
608+
}
609+
}
566610
"warning" => warnings.push(value.to_string()),
567611
"rerun-if-changed" => rerun_if_changed.push(PathBuf::from(value)),
568612
"rerun-if-env-changed" => rerun_if_env_changed.push(value.to_string()),
@@ -813,10 +857,12 @@ fn prev_build_output(cx: &mut Context<'_, '_>, unit: &Unit) -> (Option<BuildOutp
813857
(
814858
BuildOutput::parse_file(
815859
&output_file,
860+
unit.pkg.name(),
816861
&unit.pkg.to_string(),
817862
&prev_script_out_dir,
818863
&script_out_dir,
819864
extra_link_arg,
865+
cx.bcx.config.nightly_features_allowed,
820866
)
821867
.ok(),
822868
prev_script_out_dir,

src/cargo/core/compiler/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ pub use self::lto::Lto;
4949
use self::output_depinfo::output_depinfo;
5050
use self::unit_graph::UnitDep;
5151
pub use crate::core::compiler::unit::{Unit, UnitInterner};
52-
use crate::core::features::nightly_features_allowed;
5352
use crate::core::manifest::TargetSourcePath;
5453
use crate::core::profiles::{PanicStrategy, Profile, Strip};
5554
use crate::core::{Feature, PackageId, Target};
@@ -700,8 +699,8 @@ fn add_error_format_and_color(cx: &Context<'_, '_>, cmd: &mut ProcessBuilder, pi
700699
}
701700
cmd.arg(json);
702701

703-
if nightly_features_allowed() {
704-
let config = cx.bcx.config;
702+
let config = cx.bcx.config;
703+
if config.nightly_features_allowed {
705704
match (
706705
config.cli_unstable().terminal_width,
707706
config.shell().err_width().diagnostic_terminal_width(),

src/cargo/core/compiler/unit_graph.rs

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use crate::core::compiler::Unit;
22
use crate::core::compiler::{CompileKind, CompileMode};
33
use crate::core::profiles::{Profile, UnitFor};
4-
use crate::core::{nightly_features_allowed, PackageId, Target};
4+
use crate::core::{PackageId, Target};
55
use crate::util::interning::InternedString;
66
use crate::util::CargoResult;
7+
use crate::Config;
78
use std::collections::HashMap;
89
use std::io::Write;
910

@@ -62,8 +63,11 @@ struct SerializedUnitDep {
6263
// internal detail that is mostly used for building the graph.
6364
}
6465

65-
pub fn emit_serialized_unit_graph(root_units: &[Unit], unit_graph: &UnitGraph) -> CargoResult<()> {
66-
let is_nightly = nightly_features_allowed();
66+
pub fn emit_serialized_unit_graph(
67+
root_units: &[Unit],
68+
unit_graph: &UnitGraph,
69+
config: &Config,
70+
) -> CargoResult<()> {
6771
let mut units: Vec<(&Unit, &Vec<UnitDep>)> = unit_graph.iter().collect();
6872
units.sort_unstable();
6973
// Create a map for quick lookup for dependencies.
@@ -80,7 +84,7 @@ pub fn emit_serialized_unit_graph(root_units: &[Unit], unit_graph: &UnitGraph) -
8084
.iter()
8185
.map(|unit_dep| {
8286
// https://github.com/rust-lang/rust/issues/64260 when stabilized.
83-
let (public, noprelude) = if is_nightly {
87+
let (public, noprelude) = if config.nightly_features_allowed {
8488
(Some(unit_dep.public), Some(unit_dep.noprelude))
8589
} else {
8690
(None, None)

0 commit comments

Comments
 (0)