Skip to content

Commit e503329

Browse files
committed
Stabilize Workspace Inheritance
1 parent 92ff479 commit e503329

File tree

45 files changed

+172
-454
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+172
-454
lines changed

src/cargo/core/features.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ features! {
414414
(unstable, profile_rustflags, "", "reference/unstable.html#profile-rustflags-option"),
415415

416416
// Allow specifying rustflags directly in a profile
417-
(unstable, workspace_inheritance, "", "reference/unstable.html#workspace-inheritance"),
417+
(stable, workspace_inheritance, "1.64", "reference/unstable.html#workspace-inheritance"),
418418
}
419419

420420
pub struct Feature {

src/cargo/util/toml/mod.rs

+24-41
Original file line numberDiff line numberDiff line change
@@ -1017,19 +1017,16 @@ pub enum MaybeWorkspace<T> {
10171017
impl<T> MaybeWorkspace<T> {
10181018
fn resolve<'a>(
10191019
self,
1020-
cargo_features: &Features,
10211020
label: &str,
10221021
get_ws_field: impl FnOnce() -> CargoResult<T>,
10231022
) -> CargoResult<T> {
10241023
match self {
10251024
MaybeWorkspace::Defined(value) => Ok(value),
1026-
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => {
1027-
cargo_features.require(Feature::workspace_inheritance())?;
1028-
get_ws_field().context(format!(
1025+
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: true }) => get_ws_field()
1026+
.context(format!(
10291027
"error inheriting `{}` from workspace root manifest's `workspace.package.{}`",
10301028
label, label
1031-
))
1032-
}
1029+
)),
10331030
MaybeWorkspace::Workspace(TomlWorkspaceField { workspace: false }) => Err(anyhow!(
10341031
"`workspace=false` is unsupported for `package.{}`",
10351032
label,
@@ -1592,15 +1589,15 @@ impl TomlManifest {
15921589
let version = project
15931590
.version
15941591
.clone()
1595-
.resolve(&features, "version", || inherit()?.version())?;
1592+
.resolve("version", || inherit()?.version())?;
15961593

15971594
project.version = MaybeWorkspace::Defined(version.clone());
15981595

15991596
let pkgid = project.to_package_id(source_id, version)?;
16001597

16011598
let edition = if let Some(edition) = project.edition.clone() {
16021599
let edition: Edition = edition
1603-
.resolve(&features, "edition", || inherit()?.edition())?
1600+
.resolve("edition", || inherit()?.edition())?
16041601
.parse()
16051602
.with_context(|| "failed to parse the `edition` key")?;
16061603
project.edition = Some(MaybeWorkspace::Defined(edition.to_string()));
@@ -1625,7 +1622,7 @@ impl TomlManifest {
16251622
let rust_version = if let Some(rust_version) = &project.rust_version {
16261623
let rust_version = rust_version
16271624
.clone()
1628-
.resolve(&features, "rust_version", || inherit()?.rust_version())?;
1625+
.resolve("rust_version", || inherit()?.rust_version())?;
16291626
let req = match semver::VersionReq::parse(&rust_version) {
16301627
// Exclude semver operators like `^` and pre-release identifiers
16311628
Ok(req) if rust_version.chars().all(|c| c.is_ascii_digit() || c == '.') => req,
@@ -1716,7 +1713,6 @@ impl TomlManifest {
17161713
};
17171714

17181715
fn process_dependencies(
1719-
features: &Features,
17201716
cx: &mut Context<'_, '_>,
17211717
new_deps: Option<&BTreeMap<String, TomlDependency>>,
17221718
kind: Option<DepKind>,
@@ -1736,7 +1732,7 @@ impl TomlManifest {
17361732

17371733
let mut deps: BTreeMap<String, TomlDependency> = BTreeMap::new();
17381734
for (n, v) in dependencies.iter() {
1739-
let resolved = v.clone().resolve(features, n, cx, || inherit())?;
1735+
let resolved = v.clone().resolve(n, cx, || inherit())?;
17401736
let dep = resolved.to_dependency(n, cx, kind)?;
17411737
validate_package_name(dep.name_in_toml().as_str(), "dependency name", "")?;
17421738
cx.deps.push(dep);
@@ -1747,7 +1743,6 @@ impl TomlManifest {
17471743

17481744
// Collect the dependencies.
17491745
let dependencies = process_dependencies(
1750-
&features,
17511746
&mut cx,
17521747
me.dependencies.as_ref(),
17531748
None,
@@ -1762,7 +1757,6 @@ impl TomlManifest {
17621757
.as_ref()
17631758
.or_else(|| me.dev_dependencies2.as_ref());
17641759
let dev_deps = process_dependencies(
1765-
&features,
17661760
&mut cx,
17671761
dev_deps,
17681762
Some(DepKind::Development),
@@ -1777,7 +1771,6 @@ impl TomlManifest {
17771771
.as_ref()
17781772
.or_else(|| me.build_dependencies2.as_ref());
17791773
let build_deps = process_dependencies(
1780-
&features,
17811774
&mut cx,
17821775
build_deps,
17831776
Some(DepKind::Build),
@@ -1793,7 +1786,6 @@ impl TomlManifest {
17931786
Some(platform)
17941787
};
17951788
let deps = process_dependencies(
1796-
&features,
17971789
&mut cx,
17981790
platform.dependencies.as_ref(),
17991791
None,
@@ -1809,7 +1801,6 @@ impl TomlManifest {
18091801
.as_ref()
18101802
.or_else(|| platform.build_dependencies2.as_ref());
18111803
let build_deps = process_dependencies(
1812-
&features,
18131804
&mut cx,
18141805
build_deps,
18151806
Some(DepKind::Build),
@@ -1825,7 +1816,6 @@ impl TomlManifest {
18251816
.as_ref()
18261817
.or_else(|| platform.dev_dependencies2.as_ref());
18271818
let dev_deps = process_dependencies(
1828-
&features,
18291819
&mut cx,
18301820
dev_deps,
18311821
Some(DepKind::Development),
@@ -1872,13 +1862,13 @@ impl TomlManifest {
18721862
let exclude = project
18731863
.exclude
18741864
.clone()
1875-
.map(|mw| mw.resolve(&features, "exclude", || inherit()?.exclude()))
1865+
.map(|mw| mw.resolve("exclude", || inherit()?.exclude()))
18761866
.transpose()?
18771867
.unwrap_or_default();
18781868
let include = project
18791869
.include
18801870
.clone()
1881-
.map(|mw| mw.resolve(&features, "include", || inherit()?.include()))
1871+
.map(|mw| mw.resolve("include", || inherit()?.include()))
18821872
.transpose()?
18831873
.unwrap_or_default();
18841874
let empty_features = BTreeMap::new();
@@ -1895,67 +1885,63 @@ impl TomlManifest {
18951885
description: project
18961886
.description
18971887
.clone()
1898-
.map(|mw| mw.resolve(&features, "description", || inherit()?.description()))
1888+
.map(|mw| mw.resolve("description", || inherit()?.description()))
18991889
.transpose()?,
19001890
homepage: project
19011891
.homepage
19021892
.clone()
1903-
.map(|mw| mw.resolve(&features, "homepage", || inherit()?.homepage()))
1893+
.map(|mw| mw.resolve("homepage", || inherit()?.homepage()))
19041894
.transpose()?,
19051895
documentation: project
19061896
.documentation
19071897
.clone()
1908-
.map(|mw| mw.resolve(&features, "documentation", || inherit()?.documentation()))
1898+
.map(|mw| mw.resolve("documentation", || inherit()?.documentation()))
19091899
.transpose()?,
19101900
readme: readme_for_project(
19111901
package_root,
19121902
project
19131903
.readme
19141904
.clone()
1915-
.map(|mw| mw.resolve(&features, "readme", || inherit()?.readme(package_root)))
1905+
.map(|mw| mw.resolve("readme", || inherit()?.readme(package_root)))
19161906
.transpose()?,
19171907
),
19181908
authors: project
19191909
.authors
19201910
.clone()
1921-
.map(|mw| mw.resolve(&features, "authors", || inherit()?.authors()))
1911+
.map(|mw| mw.resolve("authors", || inherit()?.authors()))
19221912
.transpose()?
19231913
.unwrap_or_default(),
19241914
license: project
19251915
.license
19261916
.clone()
1927-
.map(|mw| mw.resolve(&features, "license", || inherit()?.license()))
1917+
.map(|mw| mw.resolve("license", || inherit()?.license()))
19281918
.transpose()?,
19291919
license_file: project
19301920
.license_file
19311921
.clone()
1932-
.map(|mw| {
1933-
mw.resolve(&features, "license", || {
1934-
inherit()?.license_file(package_root)
1935-
})
1936-
})
1922+
.map(|mw| mw.resolve("license", || inherit()?.license_file(package_root)))
19371923
.transpose()?,
19381924
repository: project
19391925
.repository
19401926
.clone()
1941-
.map(|mw| mw.resolve(&features, "repository", || inherit()?.repository()))
1927+
.map(|mw| mw.resolve("repository", || inherit()?.repository()))
19421928
.transpose()?,
19431929
keywords: project
19441930
.keywords
19451931
.clone()
1946-
.map(|mw| mw.resolve(&features, "keywords", || inherit()?.keywords()))
1932+
.map(|mw| mw.resolve("keywords", || inherit()?.keywords()))
19471933
.transpose()?
19481934
.unwrap_or_default(),
19491935
categories: project
19501936
.categories
19511937
.clone()
1952-
.map(|mw| mw.resolve(&features, "categories", || inherit()?.categories()))
1938+
.map(|mw| mw.resolve("categories", || inherit()?.categories()))
19531939
.transpose()?
19541940
.unwrap_or_default(),
19551941
badges: me
19561942
.badges
19571943
.clone()
1958-
.map(|mw| mw.resolve(&features, "badges", || inherit()?.badges()))
1944+
.map(|mw| mw.resolve("badges", || inherit()?.badges()))
19591945
.transpose()?
19601946
.unwrap_or_default(),
19611947
links: project.links.clone(),
@@ -2015,11 +2001,10 @@ impl TomlManifest {
20152001
profiles.validate(&features, &mut warnings)?;
20162002
}
20172003

2018-
let publish = project.publish.clone().map(|publish| {
2019-
publish
2020-
.resolve(&features, "publish", || inherit()?.publish())
2021-
.unwrap()
2022-
});
2004+
let publish = project
2005+
.publish
2006+
.clone()
2007+
.map(|publish| publish.resolve("publish", || inherit()?.publish()).unwrap());
20232008

20242009
project.publish = publish.clone().map(|p| MaybeWorkspace::Defined(p));
20252010

@@ -2479,7 +2464,6 @@ impl<P: ResolveToPath + Clone> TomlDependency<P> {
24792464
impl TomlDependency {
24802465
fn resolve<'a>(
24812466
self,
2482-
cargo_features: &Features,
24832467
label: &str,
24842468
cx: &mut Context<'_, '_>,
24852469
get_inheritable: impl FnOnce() -> CargoResult<&'a InheritableFields>,
@@ -2492,7 +2476,6 @@ impl TomlDependency {
24922476
features,
24932477
optional,
24942478
}) => {
2495-
cargo_features.require(Feature::workspace_inheritance())?;
24962479
let inheritable = get_inheritable()?;
24972480
inheritable.get_dependency(label).context(format!(
24982481
"error reading `dependencies.{}` from workspace root manifest's `workspace.dependencies.{}`",

src/doc/src/reference/specifying-dependencies.md

+43
Original file line numberDiff line numberDiff line change
@@ -454,8 +454,51 @@ following to the above manifest:
454454
log-debug = ['bar/log-debug'] # using 'foo/log-debug' would be an error!
455455
```
456456

457+
### Inheriting a dependency from a workspace
458+
459+
Dependencies can be inherited from a workspace by specifying the
460+
dependency in the workspace's [`[workspace.dependencies]`][workspace.dependencies] table.
461+
After that add it to the `[dependencies]` table with `dep.workspace = true`.
462+
463+
The `workspace` key can be defined with:
464+
- [`optional`][optional]: Note that the`[workspace.dependencies]` table is not allowed to specify `optional`.
465+
- [`features`][features]: These are additive with the features declared in the `[workspace.dependencies]`
466+
467+
The `workspace` key cannot be defined with:
468+
469+
| | |
470+
|------------------|--------------------|
471+
| `branch` | `default-features` |
472+
| `git` | `package` |
473+
| `path` | `registry` |
474+
| `registry-index` | `rev` |
475+
| `tag` | `version` |
476+
477+
478+
Dependencies in the `[dependencies]`, `[dev-dependencies]`, `[build-dependencies]`, and
479+
`[target."...".dependencies]` sections support the ability to reference the
480+
`[workspace.dependencies]` definition of dependencies.
481+
482+
Example:
483+
```toml
484+
[dependencies]
485+
dep.workspace = true
486+
dep2 = { workspace = true, features = ["fancy"] }
487+
dep3 = { workspace = true, optional = true }
488+
dep4 = { workspace = true, optional = true, features = ["fancy"] }
489+
490+
[build-dependencies]
491+
dep-build.workspace = true
492+
493+
[dev-dependencies]
494+
dep-dev.workspace = true
495+
```
496+
457497
[crates.io]: https://crates.io/
458498
[dev-dependencies]: #development-dependencies
499+
[workspace.dependencies]: workspaces.md#the-workspacedependencies-table
500+
[optional]: features.md#optional-dependencies
501+
[features]: features.md
459502

460503
<script>
461504
(function() {

0 commit comments

Comments
 (0)