-Z timings -- Display concurrency information
-Z doctest-xcompile -- Compile and run doctests for non-host target using runner config
-Z terminal-width -- Provide a terminal width to rustc for error truncation
- -Z namespaced-features -- Allow features with `crate:` prefix
+ -Z namespaced-features -- Allow features with `dep:` prefix
Run with 'cargo -Z [FLAG] [SUBCOMMAND]'"
);
}
// This is a special case for command-line `--features
- // crate_name/feat_name` where `crate_name` does not exist. All other
+ // dep_name/feat_name` where `dep_name` does not exist. All other
// validation is done either in `build_requirements` or
// `build_feature_map`.
for dep_name in reqs.deps.keys() {
} else {
for &f in opts.features.features.iter() {
let fv = FeatureValue::new(f);
- if fv.has_crate_prefix() {
+ if fv.has_dep_prefix() {
return Err(ActivateError::Fatal(anyhow::format_err!(
- "feature value `{}` is not allowed to use explicit `crate:` syntax",
+ "feature value `{}` is not allowed to use explicit `dep:` syntax",
fv
)));
}
self.features
}
- fn require_crate_feature(
+ fn require_dep_feature(
&mut self,
package: InternedString,
feat: InternedString,
- crate_prefix: bool,
+ dep_prefix: bool,
) -> Result<(), RequirementError> {
// If `package` is indeed an optional dependency then we activate the
// feature named `package`, but otherwise if `package` is a required
// dependency then there's no feature associated with it.
- if !crate_prefix
+ if !dep_prefix
&& self
.summary
.dependencies()
fn require_value(&mut self, fv: &FeatureValue) -> Result<(), RequirementError> {
match fv {
FeatureValue::Feature(feat) => self.require_feature(*feat)?,
- FeatureValue::Crate { dep_name } => self.require_dependency(*dep_name),
- FeatureValue::CrateFeature {
+ FeatureValue::Dep { dep_name } => self.require_dependency(*dep_name),
+ FeatureValue::DepFeature {
dep_name,
dep_feature,
- crate_prefix,
- } => self.require_crate_feature(*dep_name, *dep_feature, *crate_prefix)?,
+ dep_prefix,
+ } => self.require_dep_feature(*dep_name, *dep_feature, *dep_prefix)?,
};
Ok(())
}
match parent {
None => ActivateError::Fatal(anyhow::format_err!(
"Package `{}` does not have feature `{}`. It has an optional dependency \
- with that name, but that dependency uses the \"crate:\" \
+ with that name, but that dependency uses the \"dep:\" \
syntax in the features table, so it does not have an implicit feature with that name.",
summary.package_id(),
feat
dep_name
)),
// This code path currently isn't used, since `foo/bar`
- // and `crate:` syntax is not allowed in a dependency.
+ // and `dep:` syntax is not allowed in a dependency.
Some(p) => ActivateError::Conflict(
p,
ConflictReason::MissingFeatures(dep_name.to_string()),
msg.push_str("` does not have these features.\n");
msg.push_str(
" It has an optional dependency with that name, \
- but but that dependency uses the \"crate:\" \
+ but but that dependency uses the \"dep:\" \
syntax in the features table, so it does not have an \
implicit feature with that name.\n",
);
// For example, consider we've already processed our dependencies,
// and another package comes along and enables one of our optional
// dependencies, it will do so immediately in the
- // `FeatureValue::CrateFeature` branch, and then immediately
+ // `FeatureValue::DepFeature` branch, and then immediately
// recurse into that optional dependency. This also holds true for
// features that enable other features.
return Ok(());
FeatureValue::Feature(f) => {
self.activate_rec(pkg_id, *f, for_host)?;
}
- FeatureValue::Crate { dep_name } => {
+ FeatureValue::Dep { dep_name } => {
// Mark this dependency as activated.
self.activated_dependencies
.entry((pkg_id, self.opts.decouple_host_deps && for_host))
}
}
}
- FeatureValue::CrateFeature {
+ FeatureValue::DepFeature {
dep_name,
dep_feature,
- crate_prefix,
+ dep_prefix,
} => {
// Activate a feature within a dependency.
for (dep_pkg_id, deps) in self.deps(pkg_id, for_host) {
continue;
}
if dep.is_optional() {
- // Activate the crate on self.
- let fv = FeatureValue::Crate {
+ // Activate the dependency on self.
+ let fv = FeatureValue::Dep {
dep_name: *dep_name,
};
self.activate_fv(pkg_id, &fv, for_host)?;
- if !crate_prefix {
+ if !dep_prefix {
// To retain compatibility with old behavior,
// this also enables a feature of the same
// name.
RequiredDependencyAsFeature(InternedString),
/// A dependency listed a feature for an optional dependency, but that
- /// optional dependency is "hidden" using namespaced `crate:` syntax.
+ /// optional dependency is "hidden" using namespaced `dep:` syntax.
NonImplicitDependencyAsFeature(InternedString),
// TODO: needs more info for `activation_error`
if !namespaced_features {
if self.inner.has_namespaced_features {
bail!(
- "namespaced features with the `crate:` prefix are only allowed on \
+ "namespaced features with the `dep:` prefix are only allowed on \
the nightly channel and requires the `-Z namespaced-features` flag on the command-line"
);
}
/// and creates FeatureValues for each feature.
///
/// The returned `bool` indicates whether or not the `[features]` table
-/// included a `crate:` prefixed namespaced feature (used for gating on
+/// included a `dep:` prefixed namespaced feature (used for gating on
/// nightly).
fn build_feature_map(
features: &BTreeMap<InternedString, Vec<InternedString>>,
(*feature, fvs)
})
.collect();
- let has_namespaced_features = map.values().flatten().any(|fv| fv.has_crate_prefix());
+ let has_namespaced_features = map.values().flatten().any(|fv| fv.has_dep_prefix());
// Add implicit features for optional dependencies if they weren't
// explicitly listed anywhere.
.values()
.flatten()
.filter_map(|fv| match fv {
- Crate { dep_name }
- | CrateFeature {
+ Dep { dep_name }
+ | DepFeature {
dep_name,
- crate_prefix: true,
+ dep_prefix: true,
..
} => Some(*dep_name),
_ => None,
{
continue;
}
- let fv = Crate {
+ let fv = Dep {
dep_name: dep_name_in_toml,
};
map.insert(dep_name_in_toml, vec![fv]);
// Validate features are listed properly.
for (feature, fvs) in &map {
- if feature.starts_with("crate:") {
+ if feature.starts_with("dep:") {
bail!(
- "feature named `{}` is not allowed to start with `crate:`",
+ "feature named `{}` is not allowed to start with `dep:`",
feature
);
}
// Find data for the referenced dependency...
let dep_data = {
match fv {
- Feature(dep_name) | Crate { dep_name, .. } | CrateFeature { dep_name, .. } => {
+ Feature(dep_name) | Dep { dep_name, .. } | DepFeature { dep_name, .. } => {
dep_map.get(dep_name)
}
}
bail!(
"feature `{}` includes `{}`, but `{}` is an \
optional dependency without an implicit feature\n\
- Use `crate:{}` to enable the dependency.",
+ Use `dep:{}` to enable the dependency.",
feature,
fv,
f,
}
}
}
- Crate { dep_name } => {
+ Dep { dep_name } => {
if !is_any_dep {
bail!(
"feature `{}` includes `{}`, but `{}` is not listed as a dependency",
);
}
}
- CrateFeature { dep_name, .. } => {
+ DepFeature { dep_name, .. } => {
// Validation of the feature name will be performed in the resolver.
if !is_any_dep {
bail!(
.values()
.flatten()
.filter_map(|fv| match fv {
- Crate { dep_name } | CrateFeature { dep_name, .. } => Some(dep_name),
+ Dep { dep_name } | DepFeature { dep_name, .. } => Some(dep_name),
_ => None,
})
.collect();
{
bail!(
"optional dependency `{}` is not included in any feature\n\
- Make sure that `crate:{}` is included in one of features in the [features] table.",
+ Make sure that `dep:{}` is included in one of features in the [features] table.",
dep.name_in_toml(),
dep.name_in_toml(),
);
pub enum FeatureValue {
/// A feature enabling another feature.
Feature(InternedString),
- /// A feature enabling a dependency with `crate:dep_name` syntax.
- Crate { dep_name: InternedString },
+ /// A feature enabling a dependency with `dep:dep_name` syntax.
+ Dep { dep_name: InternedString },
/// A feature enabling a feature on a dependency with `crate_name/feat_name` syntax.
- CrateFeature {
+ DepFeature {
dep_name: InternedString,
dep_feature: InternedString,
- /// If this is true, then the feature used the `crate:` prefix, which
+ /// If this is true, then the feature used the `dep:` prefix, which
/// prevents enabling the feature named `dep_name`.
- crate_prefix: bool,
+ dep_prefix: bool,
},
}
Some(pos) => {
let (dep, dep_feat) = feature.split_at(pos);
let dep_feat = &dep_feat[1..];
- let (dep, crate_prefix) = if let Some(dep) = dep.strip_prefix("crate:") {
+ let (dep, dep_prefix) = if let Some(dep) = dep.strip_prefix("dep:") {
(dep, true)
} else {
(dep, false)
};
- FeatureValue::CrateFeature {
+ FeatureValue::DepFeature {
dep_name: InternedString::new(dep),
dep_feature: InternedString::new(dep_feat),
- crate_prefix,
+ dep_prefix,
+ }
+ }
+ None => {
+ if let Some(dep_name) = feature.strip_prefix("dep:") {
+ FeatureValue::Dep {
+ dep_name: InternedString::new(dep_name),
+ }
+ } else {
+ FeatureValue::Feature(feature)
}
}
- None if feature.starts_with("crate:") => FeatureValue::Crate {
- dep_name: InternedString::new(&feature[6..]),
- },
- None => FeatureValue::Feature(feature),
}
}
- /// Returns `true` if this feature explicitly used `crate:` syntax.
- pub fn has_crate_prefix(&self) -> bool {
- matches!(self, FeatureValue::Crate{..} | FeatureValue::CrateFeature{crate_prefix:true, ..})
+ /// Returns `true` if this feature explicitly used `dep:` syntax.
+ pub fn has_dep_prefix(&self) -> bool {
+ matches!(self, FeatureValue::Dep{..} | FeatureValue::DepFeature{dep_prefix:true, ..})
}
}
use self::FeatureValue::*;
match self {
Feature(feat) => write!(f, "{}", feat),
- Crate { dep_name } => write!(f, "crate:{}", dep_name),
- CrateFeature {
+ Dep { dep_name } => write!(f, "dep:{}", dep_name),
+ DepFeature {
dep_name,
dep_feature,
- crate_prefix: true,
- } => write!(f, "crate:{}/{}", dep_name, dep_feature),
- CrateFeature {
+ dep_prefix: true,
+ } => write!(f, "dep:{}/{}", dep_name, dep_feature),
+ DepFeature {
dep_name,
dep_feature,
- crate_prefix: false,
+ dep_prefix: false,
} => write!(f, "{}/{}", dep_name, dep_feature),
}
}
))?;
}
}
- FeatureValue::Crate { .. }
- | FeatureValue::CrateFeature {
- crate_prefix: true, ..
+ FeatureValue::Dep { .. }
+ | FeatureValue::DepFeature {
+ dep_prefix: true, ..
} => {
anyhow::bail!(
"invalid feature `{}` in required-features of target `{}`: \
- `crate:` prefixed feature values are not allowed in required-features",
+ `dep:` prefixed feature values are not allowed in required-features",
fv,
target_name
);
}
// Handling of dependent_crate/dependent_crate_feature syntax
- FeatureValue::CrateFeature {
+ FeatureValue::DepFeature {
dep_name,
dep_feature,
- crate_prefix: false,
+ dep_prefix: false,
} => {
match resolve
.deps(summary.package_id())
package_index,
);
}
- FeatureValue::Crate { .. } => {}
- FeatureValue::CrateFeature {
+ FeatureValue::Dep { .. } => {}
+ FeatureValue::DepFeature {
dep_name,
dep_feature,
- crate_prefix,
+ dep_prefix,
} => {
let dep_indexes = match graph.dep_name_map[&package_index].get(dep_name) {
Some(indexes) => indexes.clone(),
};
for (dep_index, is_optional) in dep_indexes {
let dep_pkg_id = graph.package_id_for_index(dep_index);
- if is_optional && !crate_prefix {
+ if is_optional && !dep_prefix {
// Activate the optional dep on self.
add_feature(
graph,
use std::path::Path;
use std::str;
-fn make_crate_prefix(name: &str) -> String {
+fn make_dep_prefix(name: &str) -> String {
match name.len() {
1 => String::from("1"),
2 => String::from("2"),
{
write!(url, "/{}/{}/download", CRATE_TEMPLATE, VERSION_TEMPLATE).unwrap();
}
- let prefix = make_crate_prefix(&*pkg.name());
+ let prefix = make_dep_prefix(&*pkg.name());
let url = url
.replace(CRATE_TEMPLATE, &*pkg.name())
.replace(VERSION_TEMPLATE, &pkg.version().to_string())
#[cfg(test)]
mod tests {
- use super::make_crate_prefix;
+ use super::make_dep_prefix;
#[test]
- fn crate_prefix() {
- assert_eq!(make_crate_prefix("a"), "1");
- assert_eq!(make_crate_prefix("ab"), "2");
- assert_eq!(make_crate_prefix("abc"), "3/a");
- assert_eq!(make_crate_prefix("Abc"), "3/A");
- assert_eq!(make_crate_prefix("AbCd"), "Ab/Cd");
- assert_eq!(make_crate_prefix("aBcDe"), "aB/cD");
+ fn dep_prefix() {
+ assert_eq!(make_dep_prefix("a"), "1");
+ assert_eq!(make_dep_prefix("ab"), "2");
+ assert_eq!(make_dep_prefix("abc"), "3/a");
+ assert_eq!(make_dep_prefix("Abc"), "3/A");
+ assert_eq!(make_dep_prefix("AbCd"), "Ab/Cd");
+ assert_eq!(make_dep_prefix("aBcDe"), "aB/cD");
}
}
* Features may now be defined with the same name as a dependency.
* Optional dependencies can be explicitly enabled in the `[features]` table
- with the `crate:` prefix, which enables the dependency without enabling a
+ with the `dep:` prefix, which enables the dependency without enabling a
feature of the same name.
By default, an optional dependency `foo` will define a feature `foo =
-["crate:foo"]` *unless* `crate:foo` is mentioned in any other feature, or the
+["dep:foo"]` *unless* `dep:foo` is mentioned in any other feature, or the
`foo` feature is already defined. This helps prevent unnecessary boilerplate
of listing every optional dependency, but still allows you to override the
implicit feature.
lazy_static = { version = "1.4.0", optional = true }
[features]
-regex = ["crate:regex", "crate:lazy_static"]
+regex = ["dep:regex", "dep:lazy_static"]
```
In this example, the "regex" feature enables both `regex` and `lazy_static`.
serde = {version = "1.0", optional = true }
[features]
-serde = ["crate:serde", "bigdecimal/serde", "chrono/serde", "num-bigint/serde"]
+serde = ["dep:serde", "bigdecimal/serde", "chrono/serde", "num-bigint/serde"]
```
In this case, `serde` is a natural name to use for a feature, because it is
#[cargo_test]
fn gated() {
- // Need namespaced-features to use `crate:` syntax.
+ // Need namespaced-features to use `dep:` syntax.
Package::new("bar", "1.0.0").publish();
let p = project()
.file(
bar = { version = "1.0", optional = true }
[features]
- foo = ["crate:bar"]
+ foo = ["dep:bar"]
"#,
)
.file("src/lib.rs", "")
[ERROR] failed to parse manifest at `[..]/foo/Cargo.toml`
Caused by:
- namespaced features with the `crate:` prefix are only allowed on the nightly channel \
+ namespaced features with the `dep:` prefix are only allowed on the nightly channel \
and requires the `-Z namespaced-features` flag on the command-line
",
)
#[cargo_test]
fn dependency_gate_ignored() {
- // Dependencies with `crate:` features are ignored in the registry if not on nightly.
+ // Dependencies with `dep:` features are ignored in the registry if not on nightly.
Package::new("baz", "1.0.0").publish();
Package::new("bar", "1.0.0")
.add_dep(Dependency::new("baz", "1.0").optional(true))
- .feature("feat", &["crate:baz"])
+ .feature("feat", &["dep:baz"])
.publish();
let p = project()
.file(
#[cargo_test]
fn dependency_with_crate_syntax() {
- // Registry dependency uses crate: syntax.
+ // Registry dependency uses dep: syntax.
Package::new("baz", "1.0.0").publish();
Package::new("bar", "1.0.0")
.add_dep(Dependency::new("baz", "1.0").optional(true))
- .feature("feat", &["crate:baz"])
+ .feature("feat", &["dep:baz"])
.publish();
let p = project()
.file(
#[cargo_test]
fn namespaced_invalid_dependency() {
- // Specifies a crate:name that doesn't exist.
+ // Specifies a dep:name that doesn't exist.
let p = project()
.file(
"Cargo.toml",
version = "0.0.1"
[features]
- bar = ["crate:baz"]
+ bar = ["dep:baz"]
"#,
)
.file("src/main.rs", "")
[ERROR] failed to parse manifest at `[..]`
Caused by:
- feature `bar` includes `crate:baz`, but `baz` is not listed as a dependency
+ feature `bar` includes `dep:baz`, but `baz` is not listed as a dependency
",
)
.run();
#[cargo_test]
fn namespaced_non_optional_dependency() {
- // Specifies a crate:name for a dependency that is not optional.
+ // Specifies a dep:name for a dependency that is not optional.
let p = project()
.file(
"Cargo.toml",
version = "0.0.1"
[features]
- bar = ["crate:baz"]
+ bar = ["dep:baz"]
[dependencies]
baz = "0.1"
[ERROR] failed to parse manifest at `[..]`
Caused by:
- feature `bar` includes `crate:baz`, but `baz` is not an optional dependency
+ feature `bar` includes `dep:baz`, but `baz` is not an optional dependency
A non-optional dependency of the same name is defined; consider adding `optional = true` to its definition.
",
)
Caused by:
optional dependency `baz` is not included in any feature
- Make sure that `crate:baz` is included in one of features in the [features] table.
+ Make sure that `dep:baz` is included in one of features in the [features] table.
",
)
.run();
version = "0.0.1"
[features]
- baz = ["crate:baz"]
+ baz = ["dep:baz"]
[dependencies]
baz = { version = "0.1", optional = true }
#[cargo_test]
fn no_implicit_feature() {
- // Using `crate:` will not create an implicit feature.
+ // Using `dep:` will not create an implicit feature.
Package::new("regex", "1.0.0").publish();
Package::new("lazy_static", "1.0.0").publish();
lazy_static = { version = "1.0", optional = true }
[features]
- regex = ["crate:regex", "crate:lazy_static"]
+ regex = ["dep:regex", "dep:lazy_static"]
"#,
)
.file(
.with_stderr(
"\
[ERROR] Package `foo v0.1.0 [..]` does not have feature `lazy_static`. \
-It has an optional dependency with that name, but that dependency uses the \"crate:\" \
+It has an optional dependency with that name, but that dependency uses the \"dep:\" \
syntax in the features table, so it does not have an implicit feature with that name.
",
)
#[cargo_test]
fn crate_feature_explicit() {
- // crate:name/feature syntax shouldn't set implicit feature.
+ // dep:name/feature syntax shouldn't set implicit feature.
Package::new("bar", "1.0.0")
.file(
"src/lib.rs",
bar = {version = "1.0", optional=true}
[features]
- f1 = ["crate:bar/feat"]
+ f1 = ["dep:bar/feat"]
"#,
)
.file(
#[cargo_test]
fn crate_syntax_bad_name() {
- // "crate:bar" = []
+ // "dep:bar" = []
Package::new("bar", "1.0.0").publish();
let p = project()
.file(
bar = { version="1.0", optional=true }
[features]
- "crate:bar" = []
+ "dep:bar" = []
"#,
)
.file("src/lib.rs", "")
.build();
- p.cargo("check -Z namespaced-features --features crate:bar")
+ p.cargo("check -Z namespaced-features --features dep:bar")
.masquerade_as_nightly_cargo()
.with_status(101)
.with_stderr(
[ERROR] failed to parse manifest at [..]/foo/Cargo.toml`
Caused by:
- feature named `crate:bar` is not allowed to start with `crate:`
+ feature named `dep:bar` is not allowed to start with `dep:`
",
)
.run();
#[cargo_test]
fn crate_syntax_in_dep() {
- // features = ["crate:baz"]
+ // features = ["dep:baz"]
Package::new("baz", "1.0.0").publish();
Package::new("bar", "1.0.0")
.add_dep(Dependency::new("baz", "1.0").optional(true))
version = "0.1.0"
[dependencies]
- bar = { version = "1.0", features = ["crate:baz"] }
+ bar = { version = "1.0", features = ["dep:baz"] }
"#,
)
.file("src/lib.rs", "")
.with_stderr(
"\
[UPDATING] [..]
-[ERROR] feature value `crate:baz` is not allowed to use explicit `crate:` syntax
+[ERROR] feature value `dep:baz` is not allowed to use explicit `dep:` syntax
",
)
.run();
#[cargo_test]
fn crate_syntax_cli() {
- // --features crate:bar
+ // --features dep:bar
Package::new("bar", "1.0.0").publish();
let p = project()
.file(
.file("src/lib.rs", "")
.build();
- p.cargo("check -Z namespaced-features --features crate:bar")
+ p.cargo("check -Z namespaced-features --features dep:bar")
.masquerade_as_nightly_cargo()
.with_status(101)
.with_stderr(
"\
[UPDATING] [..]
-[ERROR] feature value `crate:bar` is not allowed to use explicit `crate:` syntax
+[ERROR] feature value `dep:bar` is not allowed to use explicit `dep:` syntax
",
)
.run();
#[cargo_test]
fn crate_required_features() {
- // required-features = ["crate:bar"]
+ // required-features = ["dep:bar"]
Package::new("bar", "1.0.0").publish();
let p = project()
.file(
[[bin]]
name = "foo"
- required-features = ["crate:bar"]
+ required-features = ["dep:bar"]
"#,
)
.file("src/main.rs", "fn main() {}")
.with_stderr(
"\
[UPDATING] [..]
-[ERROR] invalid feature `crate:bar` in required-features of target `foo`: \
-`crate:` prefixed feature values are not allowed in required-features
+[ERROR] invalid feature `dep:bar` in required-features of target `foo`: \
+`dep:` prefixed feature values are not allowed in required-features
",
)
.run();
#[cargo_test]
fn json_exposed() {
- // Checks that the implicit crate: values are exposed in JSON.
+ // Checks that the implicit dep: values are exposed in JSON.
Package::new("bar", "1.0.0").publish();
let p = project()
.file(
"dependencies": "{...}",
"targets": "{...}",
"features": {
- "bar": ["crate:bar"]
+ "bar": ["dep:bar"]
},
"manifest_path": "[..]foo/Cargo.toml",
"metadata": null,
[features]
f1 = ["bar/bar_feat"]
- bar = ["crate:bar", "f2"]
+ bar = ["dep:bar", "f2"]
f2 = []
"#,
)
bar = { version = "1.0", optional = true }
[features]
- feat1 = ["crate:bar"]
+ feat1 = ["dep:bar"]
feat2 = ["bar"]
"#,
)
Caused by:
feature `feat2` includes `bar`, but `bar` is an optional dependency without an implicit feature
- Use `crate:bar` to enable the dependency.
+ Use `dep:bar` to enable the dependency.
",
)
.run();
Package::new("baz", "1.0.0").publish();
Package::new("bar", "1.0.0")
.add_dep(Dependency::new("baz", "1.0").optional(true))
- .feature("feat1", &["crate:baz"])
+ .feature("feat1", &["dep:baz"])
.feature("feat2", &[])
.publish();
let p = project()
[features]
a = ["bar/feat2"]
- b = ["crate:bar/feat2"]
- bar = ["crate:bar"]
+ b = ["dep:bar/feat2"]
+ bar = ["dep:bar"]
"#,
)
.file("src/lib.rs", "")