Skip to content

Commit 00615fc

Browse files
committed
Add more helpful message with stabilized -Z flags.
Previously, when something was stabilized, Cargo would spit out a very unhelpful error message about an unknown -Z flag. This changes it so that it displays a helpful warning (or error).
1 parent ff349f0 commit 00615fc

File tree

6 files changed

+143
-16
lines changed

6 files changed

+143
-16
lines changed

src/cargo/core/features.rs

Lines changed: 88 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ use anyhow::{bail, Error};
5454
use serde::{Deserialize, Serialize};
5555

5656
use crate::util::errors::CargoResult;
57+
use crate::util::indented_lines;
5758

5859
pub const SEE_CHANNELS: &str =
5960
"See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information \
@@ -380,6 +381,40 @@ pub struct CliUnstable {
380381
pub credential_process: bool,
381382
}
382383

384+
const STABILIZED_COMPILE_PROGRESS: &str = "The progress bar is now always \
385+
enabled when used on an interactive console.\n\
386+
See https://doc.rust-lang.org/cargo/reference/config.html#termprogresswhen \
387+
for information on controlling the progress bar.";
388+
389+
const STABILIZED_OFFLINE: &str = "Offline mode is now available via the \
390+
--offline CLI option";
391+
392+
const STABILIZED_CACHE_MESSAGES: &str = "Message caching is now always enabled.";
393+
394+
const STABILIZED_INSTALL_UPGRADE: &str = "Packages are now always upgraded if \
395+
they appear out of date.\n\
396+
See https://doc.rust-lang.org/cargo/commands/cargo-install.html for more \
397+
information on how upgrading works.";
398+
399+
const STABILIZED_CONFIG_PROFILE: &str = "See \
400+
https://doc.rust-lang.org/cargo/reference/config.html#profile for more \
401+
information about specifying profiles in config.";
402+
403+
const STABILIZED_CRATE_VERSIONS: &str = "The crate version is now \
404+
automatically added to the documentation.";
405+
406+
const STABILIZED_PACKAGE_FEATURES: &str = "Enhanced feature flag behavior is now \
407+
available in virtual workspaces, and `member/feature-name` syntax is also \
408+
always available. Other extensions require setting `resolver = \"2\"` in \
409+
Cargo.toml.\n\
410+
See https://doc.rust-lang.org/nightly/cargo/reference/features.html#resolver-version-2-command-line-flags \
411+
for more information.";
412+
413+
const STABILIZED_FEATURES: &str = "The new feature resolver is now available \
414+
by specifying `resolver = \"2\"` in Cargo.toml.\n\
415+
See https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-resolver-version-2 \
416+
for more information.";
417+
383418
fn deserialize_build_std<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
384419
where
385420
D: serde::Deserializer<'de>,
@@ -395,7 +430,7 @@ where
395430
}
396431

397432
impl CliUnstable {
398-
pub fn parse(&mut self, flags: &[String]) -> CargoResult<()> {
433+
pub fn parse(&mut self, flags: &[String]) -> CargoResult<Vec<String>> {
399434
if !flags.is_empty() && !nightly_features_allowed() {
400435
bail!(
401436
"the `-Z` flag is only accepted on the nightly channel of Cargo, \
@@ -405,13 +440,14 @@ impl CliUnstable {
405440
SEE_CHANNELS
406441
);
407442
}
443+
let mut warnings = Vec::new();
408444
for flag in flags {
409-
self.add(flag)?;
445+
self.add(flag, &mut warnings)?;
410446
}
411-
Ok(())
447+
Ok(warnings)
412448
}
413449

414-
fn add(&mut self, flag: &str) -> CargoResult<()> {
450+
fn add(&mut self, flag: &str, warnings: &mut Vec<String>) -> CargoResult<()> {
415451
let mut parts = flag.splitn(2, '=');
416452
let k = parts.next().unwrap();
417453
let v = parts.next();
@@ -456,6 +492,26 @@ impl CliUnstable {
456492
})
457493
}
458494

495+
let mut stabilized_warn = |key: &str, version: &str, message: &str| {
496+
warnings.push(format!(
497+
"flag `-Z {}` has been stabilized in the {} release, \
498+
and is no longer necessary\n{}",
499+
key,
500+
version,
501+
indented_lines(message)
502+
));
503+
};
504+
505+
// Use this if the behavior now requires another mechanism to enable.
506+
let stabilized_err = |key: &str, version: &str, message: &str| {
507+
Err(anyhow::format_err!(
508+
"flag `-Z {}` has been stabilized in the {} release\n{}",
509+
key,
510+
version,
511+
indented_lines(message)
512+
))
513+
};
514+
459515
match k {
460516
"print-im-a-teapot" => self.print_im_a_teapot = parse_bool(k, v)?,
461517
"unstable-options" => self.unstable_options = parse_empty(k, v)?,
@@ -477,7 +533,27 @@ impl CliUnstable {
477533
"doctest-xcompile" => self.doctest_xcompile = parse_empty(k, v)?,
478534
"panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?,
479535
"jobserver-per-rustc" => self.jobserver_per_rustc = parse_empty(k, v)?,
480-
"features" => self.features = Some(parse_features(v)),
536+
"features" => {
537+
// For now this is still allowed (there are still some
538+
// unstable options like "compare"). This should be removed at
539+
// some point, and migrate to a new -Z flag for any future
540+
// things.
541+
let feats = parse_features(v);
542+
let stab: Vec<_> = feats
543+
.iter()
544+
.filter(|feat| {
545+
matches!(
546+
feat.as_str(),
547+
"build_dep" | "host_dep" | "dev_dep" | "itarget" | "all"
548+
)
549+
})
550+
.collect();
551+
if !stab.is_empty() || feats.is_empty() {
552+
// Make this stabilized_err once -Zfeature support is removed.
553+
stabilized_warn(k, "1.51", STABILIZED_FEATURES);
554+
}
555+
self.features = Some(feats);
556+
}
481557
"separate-nightlies" => self.separate_nightlies = parse_empty(k, v)?,
482558
"multitarget" => self.multitarget = parse_empty(k, v)?,
483559
"rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?,
@@ -486,6 +562,13 @@ impl CliUnstable {
486562
"weak-dep-features" => self.weak_dep_features = parse_empty(k, v)?,
487563
"extra-link-arg" => self.extra_link_arg = parse_empty(k, v)?,
488564
"credential-process" => self.credential_process = parse_empty(k, v)?,
565+
"compile-progress" => stabilized_warn(k, "1.30", STABILIZED_COMPILE_PROGRESS),
566+
"offline" => stabilized_err(k, "1.36", STABILIZED_OFFLINE)?,
567+
"cache-messages" => stabilized_warn(k, "1.40", STABILIZED_CACHE_MESSAGES),
568+
"install-upgrade" => stabilized_warn(k, "1.41", STABILIZED_INSTALL_UPGRADE),
569+
"config-profile" => stabilized_warn(k, "1.43", STABILIZED_CONFIG_PROFILE),
570+
"crate-versions" => stabilized_warn(k, "1.47", STABILIZED_CRATE_VERSIONS),
571+
"package-features" => stabilized_warn(k, "1.51", STABILIZED_PACKAGE_FEATURES),
489572
_ => bail!("unknown `-Z` flag specified: {}", k),
490573
}
491574

src/cargo/lib.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ use log::debug;
3737
use std::fmt;
3838

3939
pub use crate::util::errors::{InternalError, VerboseError};
40-
pub use crate::util::{CargoResult, CliError, CliResult, Config};
40+
pub use crate::util::{indented_lines, CargoResult, CliError, CliResult, Config};
4141

4242
pub const CARGO_ENV: &str = "CARGO";
4343

@@ -163,13 +163,11 @@ fn _display_error(err: &Error, shell: &mut Shell, as_err: bool) -> bool {
163163
return true;
164164
}
165165
drop(writeln!(shell.err(), "\nCaused by:"));
166-
for line in cause.to_string().lines() {
167-
if line.is_empty() {
168-
drop(writeln!(shell.err()));
169-
} else {
170-
drop(writeln!(shell.err(), " {}", line));
171-
}
172-
}
166+
drop(write!(
167+
shell.err(),
168+
"{}",
169+
indented_lines(&cause.to_string())
170+
));
173171
}
174172
false
175173
}

src/cargo/util/config/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,9 @@ impl Config {
704704
unstable_flags: &[String],
705705
cli_config: &[String],
706706
) -> CargoResult<()> {
707-
self.unstable_flags.parse(unstable_flags)?;
707+
for warning in self.unstable_flags.parse(unstable_flags)? {
708+
self.shell().warn(warning)?;
709+
}
708710
if !unstable_flags.is_empty() {
709711
// store a copy of the cli flags separately for `load_unstable_flags_from_config`
710712
// (we might also need it again for `reload_rooted_at`)

src/cargo/util/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,15 @@ pub fn elapsed(duration: Duration) -> String {
7979
pub fn is_ci() -> bool {
8080
std::env::var("CI").is_ok() || std::env::var("TF_BUILD").is_ok()
8181
}
82+
83+
pub fn indented_lines(text: &str) -> String {
84+
text.lines()
85+
.map(|line| {
86+
if line.is_empty() {
87+
String::from("\n")
88+
} else {
89+
format!(" {}\n", line)
90+
}
91+
})
92+
.collect()
93+
}

tests/testsuite/cargo_features.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -356,3 +356,34 @@ Caused by:
356356
)
357357
.run();
358358
}
359+
360+
#[cargo_test]
361+
fn z_stabilized() {
362+
let p = project().file("src/lib.rs", "").build();
363+
364+
p.cargo("check -Z cache-messages")
365+
.masquerade_as_nightly_cargo()
366+
.with_stderr(
367+
"\
368+
warning: flag `-Z cache-messages` has been stabilized in the 1.40 release, \
369+
and is no longer necessary
370+
Message caching is now always enabled.
371+
372+
[CHECKING] foo [..]
373+
[FINISHED] [..]
374+
",
375+
)
376+
.run();
377+
378+
p.cargo("check -Z offline")
379+
.masquerade_as_nightly_cargo()
380+
.with_status(101)
381+
.with_stderr(
382+
"\
383+
error: flag `-Z offline` has been stabilized in the 1.36 release
384+
Offline mode is now available via the --offline CLI option
385+
386+
",
387+
)
388+
.run();
389+
}

tests/testsuite/weak_dep_features.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ optional dependency with `?` is not allowed in required-features
336336

337337
#[cargo_test]
338338
fn weak_with_host_decouple() {
339-
// -Z weak-opt-features with -Z features=host
339+
// -Z weak-opt-features with new resolver
340340
//
341341
// foo v0.1.0
342342
// └── common v1.0.0
@@ -390,6 +390,7 @@ fn weak_with_host_decouple() {
390390
[package]
391391
name = "foo"
392392
version = "0.1.0"
393+
resolver = "2"
393394
394395
[dependencies]
395396
common = { version = "1.0", features = ["feat"] }
@@ -416,7 +417,7 @@ fn weak_with_host_decouple() {
416417
)
417418
.build();
418419

419-
p.cargo("run -Z weak-dep-features -Z features=host_dep")
420+
p.cargo("run -Z weak-dep-features")
420421
.masquerade_as_nightly_cargo()
421422
.with_stderr(
422423
"\

0 commit comments

Comments
 (0)