From 00615fc51a5d47b96adba18d1e5616671680e314 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Wed, 20 Jan 2021 19:46:50 -0800 Subject: [PATCH] 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). --- src/cargo/core/features.rs | 93 ++++++++++++++++++++++++++-- src/cargo/lib.rs | 14 ++--- src/cargo/util/config/mod.rs | 4 +- src/cargo/util/mod.rs | 12 ++++ tests/testsuite/cargo_features.rs | 31 ++++++++++ tests/testsuite/weak_dep_features.rs | 5 +- 6 files changed, 143 insertions(+), 16 deletions(-) diff --git a/src/cargo/core/features.rs b/src/cargo/core/features.rs index 45df0d247..0a4ce2a28 100644 --- a/src/cargo/core/features.rs +++ b/src/cargo/core/features.rs @@ -54,6 +54,7 @@ use anyhow::{bail, Error}; use serde::{Deserialize, Serialize}; use crate::util::errors::CargoResult; +use crate::util::indented_lines; pub const SEE_CHANNELS: &str = "See https://doc.rust-lang.org/book/appendix-07-nightly-rust.html for more information \ @@ -380,6 +381,40 @@ pub struct CliUnstable { pub credential_process: bool, } +const STABILIZED_COMPILE_PROGRESS: &str = "The progress bar is now always \ + enabled when used on an interactive console.\n\ + See https://doc.rust-lang.org/cargo/reference/config.html#termprogresswhen \ + for information on controlling the progress bar."; + +const STABILIZED_OFFLINE: &str = "Offline mode is now available via the \ + --offline CLI option"; + +const STABILIZED_CACHE_MESSAGES: &str = "Message caching is now always enabled."; + +const STABILIZED_INSTALL_UPGRADE: &str = "Packages are now always upgraded if \ + they appear out of date.\n\ + See https://doc.rust-lang.org/cargo/commands/cargo-install.html for more \ + information on how upgrading works."; + +const STABILIZED_CONFIG_PROFILE: &str = "See \ + https://doc.rust-lang.org/cargo/reference/config.html#profile for more \ + information about specifying profiles in config."; + +const STABILIZED_CRATE_VERSIONS: &str = "The crate version is now \ + automatically added to the documentation."; + +const STABILIZED_PACKAGE_FEATURES: &str = "Enhanced feature flag behavior is now \ + available in virtual workspaces, and `member/feature-name` syntax is also \ + always available. Other extensions require setting `resolver = \"2\"` in \ + Cargo.toml.\n\ + See https://doc.rust-lang.org/nightly/cargo/reference/features.html#resolver-version-2-command-line-flags \ + for more information."; + +const STABILIZED_FEATURES: &str = "The new feature resolver is now available \ + by specifying `resolver = \"2\"` in Cargo.toml.\n\ + See https://doc.rust-lang.org/nightly/cargo/reference/features.html#feature-resolver-version-2 \ + for more information."; + fn deserialize_build_std<'de, D>(deserializer: D) -> Result>, D::Error> where D: serde::Deserializer<'de>, @@ -395,7 +430,7 @@ where } impl CliUnstable { - pub fn parse(&mut self, flags: &[String]) -> CargoResult<()> { + pub fn parse(&mut self, flags: &[String]) -> CargoResult> { if !flags.is_empty() && !nightly_features_allowed() { bail!( "the `-Z` flag is only accepted on the nightly channel of Cargo, \ @@ -405,13 +440,14 @@ impl CliUnstable { SEE_CHANNELS ); } + let mut warnings = Vec::new(); for flag in flags { - self.add(flag)?; + self.add(flag, &mut warnings)?; } - Ok(()) + Ok(warnings) } - fn add(&mut self, flag: &str) -> CargoResult<()> { + fn add(&mut self, flag: &str, warnings: &mut Vec) -> CargoResult<()> { let mut parts = flag.splitn(2, '='); let k = parts.next().unwrap(); let v = parts.next(); @@ -456,6 +492,26 @@ impl CliUnstable { }) } + let mut stabilized_warn = |key: &str, version: &str, message: &str| { + warnings.push(format!( + "flag `-Z {}` has been stabilized in the {} release, \ + and is no longer necessary\n{}", + key, + version, + indented_lines(message) + )); + }; + + // Use this if the behavior now requires another mechanism to enable. + let stabilized_err = |key: &str, version: &str, message: &str| { + Err(anyhow::format_err!( + "flag `-Z {}` has been stabilized in the {} release\n{}", + key, + version, + indented_lines(message) + )) + }; + match k { "print-im-a-teapot" => self.print_im_a_teapot = parse_bool(k, v)?, "unstable-options" => self.unstable_options = parse_empty(k, v)?, @@ -477,7 +533,27 @@ impl CliUnstable { "doctest-xcompile" => self.doctest_xcompile = parse_empty(k, v)?, "panic-abort-tests" => self.panic_abort_tests = parse_empty(k, v)?, "jobserver-per-rustc" => self.jobserver_per_rustc = parse_empty(k, v)?, - "features" => self.features = Some(parse_features(v)), + "features" => { + // For now this is still allowed (there are still some + // unstable options like "compare"). This should be removed at + // some point, and migrate to a new -Z flag for any future + // things. + let feats = parse_features(v); + let stab: Vec<_> = feats + .iter() + .filter(|feat| { + matches!( + feat.as_str(), + "build_dep" | "host_dep" | "dev_dep" | "itarget" | "all" + ) + }) + .collect(); + if !stab.is_empty() || feats.is_empty() { + // Make this stabilized_err once -Zfeature support is removed. + stabilized_warn(k, "1.51", STABILIZED_FEATURES); + } + self.features = Some(feats); + } "separate-nightlies" => self.separate_nightlies = parse_empty(k, v)?, "multitarget" => self.multitarget = parse_empty(k, v)?, "rustdoc-map" => self.rustdoc_map = parse_empty(k, v)?, @@ -486,6 +562,13 @@ impl CliUnstable { "weak-dep-features" => self.weak_dep_features = parse_empty(k, v)?, "extra-link-arg" => self.extra_link_arg = parse_empty(k, v)?, "credential-process" => self.credential_process = parse_empty(k, v)?, + "compile-progress" => stabilized_warn(k, "1.30", STABILIZED_COMPILE_PROGRESS), + "offline" => stabilized_err(k, "1.36", STABILIZED_OFFLINE)?, + "cache-messages" => stabilized_warn(k, "1.40", STABILIZED_CACHE_MESSAGES), + "install-upgrade" => stabilized_warn(k, "1.41", STABILIZED_INSTALL_UPGRADE), + "config-profile" => stabilized_warn(k, "1.43", STABILIZED_CONFIG_PROFILE), + "crate-versions" => stabilized_warn(k, "1.47", STABILIZED_CRATE_VERSIONS), + "package-features" => stabilized_warn(k, "1.51", STABILIZED_PACKAGE_FEATURES), _ => bail!("unknown `-Z` flag specified: {}", k), } diff --git a/src/cargo/lib.rs b/src/cargo/lib.rs index bccb41121..1f8ceb691 100644 --- a/src/cargo/lib.rs +++ b/src/cargo/lib.rs @@ -37,7 +37,7 @@ use log::debug; use std::fmt; pub use crate::util::errors::{InternalError, VerboseError}; -pub use crate::util::{CargoResult, CliError, CliResult, Config}; +pub use crate::util::{indented_lines, CargoResult, CliError, CliResult, Config}; pub const CARGO_ENV: &str = "CARGO"; @@ -163,13 +163,11 @@ fn _display_error(err: &Error, shell: &mut Shell, as_err: bool) -> bool { return true; } drop(writeln!(shell.err(), "\nCaused by:")); - for line in cause.to_string().lines() { - if line.is_empty() { - drop(writeln!(shell.err())); - } else { - drop(writeln!(shell.err(), " {}", line)); - } - } + drop(write!( + shell.err(), + "{}", + indented_lines(&cause.to_string()) + )); } false } diff --git a/src/cargo/util/config/mod.rs b/src/cargo/util/config/mod.rs index 5cd6bd852..b492e94ed 100644 --- a/src/cargo/util/config/mod.rs +++ b/src/cargo/util/config/mod.rs @@ -704,7 +704,9 @@ impl Config { unstable_flags: &[String], cli_config: &[String], ) -> CargoResult<()> { - self.unstable_flags.parse(unstable_flags)?; + for warning in self.unstable_flags.parse(unstable_flags)? { + self.shell().warn(warning)?; + } if !unstable_flags.is_empty() { // store a copy of the cli flags separately for `load_unstable_flags_from_config` // (we might also need it again for `reload_rooted_at`) diff --git a/src/cargo/util/mod.rs b/src/cargo/util/mod.rs index 11ac2bae6..b9ca5797f 100644 --- a/src/cargo/util/mod.rs +++ b/src/cargo/util/mod.rs @@ -79,3 +79,15 @@ pub fn elapsed(duration: Duration) -> String { pub fn is_ci() -> bool { std::env::var("CI").is_ok() || std::env::var("TF_BUILD").is_ok() } + +pub fn indented_lines(text: &str) -> String { + text.lines() + .map(|line| { + if line.is_empty() { + String::from("\n") + } else { + format!(" {}\n", line) + } + }) + .collect() +} diff --git a/tests/testsuite/cargo_features.rs b/tests/testsuite/cargo_features.rs index 2b638df22..0d8aa242a 100644 --- a/tests/testsuite/cargo_features.rs +++ b/tests/testsuite/cargo_features.rs @@ -356,3 +356,34 @@ Caused by: ) .run(); } + +#[cargo_test] +fn z_stabilized() { + let p = project().file("src/lib.rs", "").build(); + + p.cargo("check -Z cache-messages") + .masquerade_as_nightly_cargo() + .with_stderr( + "\ +warning: flag `-Z cache-messages` has been stabilized in the 1.40 release, \ + and is no longer necessary + Message caching is now always enabled. + +[CHECKING] foo [..] +[FINISHED] [..] +", + ) + .run(); + + p.cargo("check -Z offline") + .masquerade_as_nightly_cargo() + .with_status(101) + .with_stderr( + "\ +error: flag `-Z offline` has been stabilized in the 1.36 release + Offline mode is now available via the --offline CLI option + +", + ) + .run(); +} diff --git a/tests/testsuite/weak_dep_features.rs b/tests/testsuite/weak_dep_features.rs index 6b8ed355a..255e5628e 100644 --- a/tests/testsuite/weak_dep_features.rs +++ b/tests/testsuite/weak_dep_features.rs @@ -336,7 +336,7 @@ optional dependency with `?` is not allowed in required-features #[cargo_test] fn weak_with_host_decouple() { - // -Z weak-opt-features with -Z features=host + // -Z weak-opt-features with new resolver // // foo v0.1.0 // └── common v1.0.0 @@ -390,6 +390,7 @@ fn weak_with_host_decouple() { [package] name = "foo" version = "0.1.0" + resolver = "2" [dependencies] common = { version = "1.0", features = ["feat"] } @@ -416,7 +417,7 @@ fn weak_with_host_decouple() { ) .build(); - p.cargo("run -Z weak-dep-features -Z features=host_dep") + p.cargo("run -Z weak-dep-features") .masquerade_as_nightly_cargo() .with_stderr( "\