Add -Zallow-features to match rustc's -Z

This commit is contained in:
Jon Gjengset 2021-03-17 15:19:54 -07:00
parent 90691f2bfe
commit 4a90ab6910
4 changed files with 136 additions and 3 deletions

View File

@ -35,6 +35,7 @@ pub fn main(config: &mut Config) -> CliResult {
"
Available unstable (nightly-only) flags:
-Z allow-features -- Allow *only* the listed unstable features
-Z avoid-dev-deps -- Avoid installing dev-dependencies if possible
-Z extra-link-arg -- Allow `cargo:rustc-link-arg` in build scripts
-Z minimal-versions -- Install minimal dependency versions instead of maximum

View File

@ -92,6 +92,7 @@
//! of that page. Update the rest of the documentation to add the new
//! feature.
use std::collections::HashSet;
use std::env;
use std::fmt;
use std::str::FromStr;
@ -415,13 +416,18 @@ impl Features {
let mut ret = Features::default();
ret.nightly_features_allowed = config.nightly_features_allowed;
for feature in features {
ret.add(feature, warnings)?;
ret.add(feature, config, warnings)?;
ret.activated.push(feature.to_string());
}
Ok(ret)
}
fn add(&mut self, feature_name: &str, warnings: &mut Vec<String>) -> CargoResult<()> {
fn add(
&mut self,
feature_name: &str,
config: &Config,
warnings: &mut Vec<String>,
) -> CargoResult<()> {
let nightly_features_allowed = self.nightly_features_allowed;
let (slot, feature) = match self.status(feature_name) {
Some(p) => p,
@ -469,6 +475,24 @@ impl Features {
SEE_CHANNELS,
see_docs()
),
Status::Unstable
if !config
.cli_unstable()
.allow_features
.as_ref()
.map(|f| f.contains(feature_name))
.unwrap_or(true) =>
{
bail!(
"the feature `{}` is not in the list of allowed features: {:?}",
feature_name,
config
.cli_unstable()
.allow_features
.as_ref()
.expect("!unwrap_or(true) == false")
)
}
Status::Unstable => {}
Status::Removed => bail!(
"the cargo feature `{}` has been removed\n\
@ -530,6 +554,8 @@ impl Features {
#[serde(default, rename_all = "kebab-case")]
pub struct CliUnstable {
pub print_im_a_teapot: bool,
pub allow_features: Option<HashSet<String>>,
pub unstable_options: bool,
pub no_index_update: bool,
pub avoid_dev_deps: bool,
@ -627,7 +653,32 @@ impl CliUnstable {
}
let mut warnings = Vec::new();
for flag in flags {
self.add(flag, &mut warnings)?;
if flag.starts_with("allow-features=") {
self.add(flag, &mut warnings)?;
}
}
if let Some(allowed) = self.allow_features.take() {
for flag in flags {
let k = flag
.splitn(2, '=')
.next()
.expect("split always yields >=1 item");
if k == "allow-features" {
} else if allowed.contains(k) {
self.add(flag, &mut warnings)?;
} else {
bail!(
"the feature `{}` is not in the list of allowed features: {:?}",
k,
allowed
);
}
}
self.allow_features = Some(allowed);
} else {
for flag in flags {
self.add(flag, &mut warnings)?;
}
}
Ok(warnings)
}
@ -655,6 +706,7 @@ impl CliUnstable {
fn parse_features(value: Option<&str>) -> Vec<String> {
match value {
None => Vec::new(),
Some("") => Vec::new(),
Some(v) => v.split(',').map(|s| s.to_string()).collect(),
}
}
@ -699,6 +751,7 @@ impl CliUnstable {
match k {
"print-im-a-teapot" => self.print_im_a_teapot = parse_bool(k, v)?,
"allow-features" => self.allow_features = Some(parse_features(v).into_iter().collect()),
"unstable-options" => self.unstable_options = parse_empty(k, v)?,
"no-index-update" => self.no_index_update = parse_empty(k, v)?,
"avoid-dev-deps" => self.avoid_dev_deps = parse_empty(k, v)?,

View File

@ -58,6 +58,27 @@ Each new feature described below should explain how to use it.
[nightly channel]: ../../book/appendix-07-nightly-rust.html
[stabilized]: https://doc.crates.io/contrib/process/unstable.html#stabilization
### allow-features
This permanently-unstable flag makes it so that only a listed set of
unstable features can be used. Specifically, if you pass
`-Zallow-features=foo,bar`, you'll continue to be able to pass `-Zfoo`
and `-Zbar` to `cargo`, but you will be unable to pass `-Zbaz`. You can
pass an empty string (`-Zallow-features=`) to disallow all unstable
features.
`-Zallow-features` also restricts which unstable features can be passed
to the `cargo-features` entry in `Cargo.toml`. If, for example, you want
to allow
```toml
cargo-features = ["test-dummy-unstable"]
```
where `test-dummy-unstable` is unstable, that features would also be
disallowed by `-Zallow-features=`, and allowed with
`-Zallow-features=test-dummy-unstable`.
### extra-link-arg
* Original Pull Request: [#7811](https://github.com/rust-lang/cargo/pull/7811)

View File

@ -113,6 +113,64 @@ release and is no longer necessary to be listed in the manifest
.run();
}
#[cargo_test]
fn allow_features() {
let p = project()
.file(
"Cargo.toml",
r#"
cargo-features = ["test-dummy-unstable"]
[package]
name = "a"
version = "0.0.1"
authors = []
im-a-teapot = true
"#,
)
.file("src/lib.rs", "")
.build();
p.cargo("-Zallow-features=test-dummy-unstable build")
.masquerade_as_nightly_cargo()
.with_stderr(
"\
[COMPILING] a [..]
[FINISHED] [..]
",
)
.run();
p.cargo("-Zallow-features=test-dummy-unstable,print-im-a-teapot -Zprint-im-a-teapot build")
.masquerade_as_nightly_cargo()
.with_stdout("im-a-teapot = true")
.with_stderr("[FINISHED] [..]")
.run();
p.cargo("-Zallow-features=test-dummy-unstable -Zprint-im-a-teapot build")
.masquerade_as_nightly_cargo()
.with_status(101)
.with_stderr(
"\
error: the feature `print-im-a-teapot` is not in the list of allowed features: {\"test-dummy-unstable\"}
",
)
.run();
p.cargo("-Zallow-features= build")
.masquerade_as_nightly_cargo()
.with_status(101)
.with_stderr(
"\
error: failed to parse manifest at `[..]`
Caused by:
the feature `test-dummy-unstable` is not in the list of allowed features: {}
",
)
.run();
}
#[cargo_test]
fn nightly_feature_requires_nightly() {
let p = project()