Skip to content

Commit 48fb957

Browse files
committed
Auto merge of #13589 - epage:toml, r=Muscraft
refactor(toml): Flatten manifest parsing ### What does this PR try to resolve? This is just a clean up but the goals are - Support diagnostics that show source by tracking `&str`, `ImDocument`, etc in `Manifest` by making each accessible in the creation of a `Manifest` - Defer warning analysis until we know what is a local vs non-local workspace by refactoring warnings out into a dedicated step - Centralize the logic for `cargo publish` stripping of dev-dependencies and their feature activations by allowing a `Summary` to be created from any "resolved" `TomlManifest` - Enumerate all build targets in the "resolved" `TomlManifest` so they get included in `cargo publish`, reducing the work done on registry dependencies and resolving problems like #13456 Along the way, this fixed a bug where we were not reporting warnings from virtual manifests ### How should we test and review this PR? ### Additional information
2 parents 403fbe2 + 4ed67e3 commit 48fb957

File tree

19 files changed

+286
-229
lines changed

19 files changed

+286
-229
lines changed

Cargo.lock

+3-3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ cargo-platform = { path = "crates/cargo-platform", version = "0.1.5" }
3333
cargo-test-macro = { path = "crates/cargo-test-macro" }
3434
cargo-test-support = { path = "crates/cargo-test-support" }
3535
cargo-util = { version = "0.2.9", path = "crates/cargo-util" }
36-
cargo-util-schemas = { version = "0.2.1", path = "crates/cargo-util-schemas" }
36+
cargo-util-schemas = { version = "0.3.0", path = "crates/cargo-util-schemas" }
3737
cargo_metadata = "0.18.1"
3838
clap = "4.5.1"
3939
color-print = "0.3.5"
@@ -97,7 +97,7 @@ tempfile = "3.10.1"
9797
thiserror = "1.0.57"
9898
time = { version = "0.3", features = ["parsing", "formatting", "serde"] }
9999
toml = "0.8.10"
100-
toml_edit = { version = "0.22.6", features = ["serde"] }
100+
toml_edit = { version = "0.22.7", features = ["serde"] }
101101
tracing = "0.1.40" # be compatible with rustc_log: https://github.com/rust-lang/rust/blob/e51e98dde6a/compiler/rustc_log/Cargo.toml#L9
102102
tracing-chrome = "0.7.1"
103103
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }

crates/cargo-util-schemas/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "cargo-util-schemas"
3-
version = "0.2.1"
3+
version = "0.3.0"
44
rust-version = "1.76.0" # MSRV:1
55
edition.workspace = true
66
license.workspace = true

crates/cargo-util-schemas/src/manifest/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
//! - Keys that exist for bookkeeping but don't correspond to the schema have a `_` prefix
77
88
use std::collections::BTreeMap;
9+
use std::collections::BTreeSet;
910
use std::fmt::{self, Display, Write};
1011
use std::path::PathBuf;
1112
use std::str;
@@ -28,6 +29,7 @@ pub use rust_version::RustVersionError;
2829
#[derive(Debug, Deserialize, Serialize)]
2930
#[serde(rename_all = "kebab-case")]
3031
pub struct TomlManifest {
32+
// when adding new fields, be sure to check whether `requires_package` should disallow them
3133
pub cargo_features: Option<Vec<String>>,
3234
pub package: Option<Box<TomlPackage>>,
3335
pub project: Option<Box<TomlPackage>>,
@@ -51,7 +53,11 @@ pub struct TomlManifest {
5153
pub workspace: Option<TomlWorkspace>,
5254
pub badges: Option<InheritableBtreeMap>,
5355
pub lints: Option<InheritableLints>,
54-
// when adding new fields, be sure to check whether `requires_package` should disallow them
56+
57+
/// Report unused keys (see also nested `_unused_keys`)
58+
/// Note: this is populated by the caller, rather than automatically
59+
#[serde(skip)]
60+
pub _unused_keys: BTreeSet<String>,
5561
}
5662

5763
impl TomlManifest {

crates/xtask-stale-label/src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
use std::fmt::Write as _;
1616
use std::path::PathBuf;
1717
use std::process;
18-
use toml_edit::Document;
18+
use toml_edit::DocumentMut;
1919

2020
fn main() {
2121
let pkg_root = std::env!("CARGO_MANIFEST_DIR");
@@ -31,7 +31,7 @@ fn main() {
3131
let mut passed = 0;
3232

3333
let toml = std::fs::read_to_string(path).expect("read from file");
34-
let doc = toml.parse::<Document>().expect("a toml");
34+
let doc = toml.parse::<DocumentMut>().expect("a toml");
3535
let autolabel = doc["autolabel"].as_table().expect("a toml table");
3636

3737
for (label, value) in autolabel.iter() {

src/bin/cargo/commands/remove.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ fn parse_section(args: &ArgMatches) -> DepTable {
160160
/// Clean up the workspace.dependencies, profile, patch, and replace sections of the root manifest
161161
/// by removing dependencies which no longer have a reference to them.
162162
fn gc_workspace(workspace: &Workspace<'_>) -> CargoResult<()> {
163-
let mut manifest: toml_edit::Document =
163+
let mut manifest: toml_edit::DocumentMut =
164164
cargo_util::paths::read(workspace.root_manifest())?.parse()?;
165165
let mut is_modified = true;
166166

@@ -315,7 +315,7 @@ fn spec_has_match(
315315

316316
/// Removes unused patches from the manifest
317317
fn gc_unused_patches(workspace: &Workspace<'_>, resolve: &Resolve) -> CargoResult<bool> {
318-
let mut manifest: toml_edit::Document =
318+
let mut manifest: toml_edit::DocumentMut =
319319
cargo_util::paths::read(workspace.root_manifest())?.parse()?;
320320
let mut modified = false;
321321

src/cargo/core/manifest.rs

+10-5
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,11 @@ impl EitherManifest {
4141
/// This is deserialized using the [`TomlManifest`] type.
4242
#[derive(Clone, Debug)]
4343
pub struct Manifest {
44+
// alternate forms of manifests:
45+
resolved_toml: Rc<TomlManifest>,
4446
summary: Summary,
47+
48+
// this form of manifest:
4549
targets: Vec<Target>,
4650
default_kind: Option<CompileKind>,
4751
forced_kind: Option<CompileKind>,
@@ -56,7 +60,6 @@ pub struct Manifest {
5660
replace: Vec<(PackageIdSpec, Dependency)>,
5761
patch: HashMap<Url, Vec<Dependency>>,
5862
workspace: WorkspaceConfig,
59-
original: Rc<TomlManifest>,
6063
unstable_features: Features,
6164
edition: Edition,
6265
rust_version: Option<RustVersion>,
@@ -386,7 +389,9 @@ compact_debug! {
386389

387390
impl Manifest {
388391
pub fn new(
392+
resolved_toml: Rc<TomlManifest>,
389393
summary: Summary,
394+
390395
default_kind: Option<CompileKind>,
391396
forced_kind: Option<CompileKind>,
392397
targets: Vec<Target>,
@@ -405,14 +410,15 @@ impl Manifest {
405410
rust_version: Option<RustVersion>,
406411
im_a_teapot: Option<bool>,
407412
default_run: Option<String>,
408-
original: Rc<TomlManifest>,
409413
metabuild: Option<Vec<String>>,
410414
resolve_behavior: Option<ResolveBehavior>,
411415
lint_rustflags: Vec<String>,
412416
embedded: bool,
413417
) -> Manifest {
414418
Manifest {
419+
resolved_toml,
415420
summary,
421+
416422
default_kind,
417423
forced_kind,
418424
targets,
@@ -430,7 +436,6 @@ impl Manifest {
430436
unstable_features,
431437
edition,
432438
rust_version,
433-
original,
434439
im_a_teapot,
435440
default_run,
436441
metabuild,
@@ -495,8 +500,8 @@ impl Manifest {
495500
pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] {
496501
&self.replace
497502
}
498-
pub fn original(&self) -> &TomlManifest {
499-
&self.original
503+
pub fn resolved_toml(&self) -> &TomlManifest {
504+
&self.resolved_toml
500505
}
501506
pub fn patch(&self) -> &HashMap<Url, Vec<Dependency>> {
502507
&self.patch

src/cargo/core/package.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ impl Package {
198198
}
199199

200200
pub fn to_registry_toml(&self, ws: &Workspace<'_>) -> CargoResult<String> {
201-
let manifest = prepare_for_publish(self.manifest().original(), ws, self.root())?;
201+
let manifest = prepare_for_publish(self.manifest().resolved_toml(), ws, self.root())?;
202202
let toml = toml::to_string_pretty(&manifest)?;
203203
Ok(format!("{}\n{}", MANIFEST_PREAMBLE, toml))
204204
}

src/cargo/core/workspace.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -420,7 +420,6 @@ impl<'gctx> Workspace<'gctx> {
420420
let source = SourceId::for_path(self.root())?;
421421

422422
let mut warnings = Vec::new();
423-
let mut nested_paths = Vec::new();
424423

425424
let mut patch = HashMap::new();
426425
for (url, deps) in config_patch.into_iter().flatten() {
@@ -442,7 +441,6 @@ impl<'gctx> Workspace<'gctx> {
442441
dep,
443442
name,
444443
source,
445-
&mut nested_paths,
446444
self.gctx,
447445
&mut warnings,
448446
/* platform */ None,
@@ -1006,7 +1004,7 @@ impl<'gctx> Workspace<'gctx> {
10061004
);
10071005
self.gctx.shell().warn(&msg)
10081006
};
1009-
if manifest.original().has_profiles() {
1007+
if manifest.resolved_toml().has_profiles() {
10101008
emit_warning("profiles")?;
10111009
}
10121010
if !manifest.replace().is_empty() {
@@ -1063,7 +1061,7 @@ impl<'gctx> Workspace<'gctx> {
10631061
return Ok(p);
10641062
}
10651063
let source_id = SourceId::for_path(manifest_path.parent().unwrap())?;
1066-
let (package, _nested_paths) = ops::read_package(manifest_path, source_id, self.gctx)?;
1064+
let package = ops::read_package(manifest_path, source_id, self.gctx)?;
10671065
loaded.insert(manifest_path.to_path_buf(), package.clone());
10681066
Ok(package)
10691067
}
@@ -1596,7 +1594,7 @@ impl<'gctx> Packages<'gctx> {
15961594
Entry::Occupied(e) => Ok(e.into_mut()),
15971595
Entry::Vacant(v) => {
15981596
let source_id = SourceId::for_path(key)?;
1599-
let (manifest, _nested_paths) = read_manifest(manifest_path, source_id, self.gctx)?;
1597+
let manifest = read_manifest(manifest_path, source_id, self.gctx)?;
16001598
Ok(v.insert(match manifest {
16011599
EitherManifest::Real(manifest) => {
16021600
MaybePackage::Package(Package::new(manifest, manifest_path))
@@ -1746,7 +1744,7 @@ pub fn find_workspace_root(
17461744
find_workspace_root_with_loader(manifest_path, gctx, |self_path| {
17471745
let key = self_path.parent().unwrap();
17481746
let source_id = SourceId::for_path(key)?;
1749-
let (manifest, _nested_paths) = read_manifest(self_path, source_id, gctx)?;
1747+
let manifest = read_manifest(self_path, source_id, gctx)?;
17501748
Ok(manifest
17511749
.workspace_config()
17521750
.get_ws_root(self_path, manifest_path))

src/cargo/ops/cargo_new.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -768,7 +768,7 @@ fn mk(gctx: &GlobalContext, opts: &MkOptions<'_>) -> CargoResult<()> {
768768
write_ignore_file(path, &ignore, vcs)?;
769769

770770
// Create `Cargo.toml` file with necessary `[lib]` and `[[bin]]` sections, if needed.
771-
let mut manifest = toml_edit::Document::new();
771+
let mut manifest = toml_edit::DocumentMut::new();
772772
manifest["package"] = toml_edit::Item::Table(toml_edit::Table::new());
773773
manifest["package"]["name"] = toml_edit::value(name);
774774
manifest["package"]["version"] = toml_edit::value("0.1.0");
@@ -814,7 +814,7 @@ fn mk(gctx: &GlobalContext, opts: &MkOptions<'_>) -> CargoResult<()> {
814814
// Sometimes the root manifest is not a valid manifest, so we only try to parse it if it is.
815815
// This should not block the creation of the new project. It is only a best effort to
816816
// inherit the workspace package keys.
817-
if let Ok(mut workspace_document) = root_manifest.parse::<toml_edit::Document>() {
817+
if let Ok(mut workspace_document) = root_manifest.parse::<toml_edit::DocumentMut>() {
818818
let display_path = get_display_path(&root_manifest_path, &path)?;
819819
let can_be_a_member = can_be_workspace_member(&display_path, &workspace_document)?;
820820
// Only try to inherit the workspace stuff if the new package can be a member of the workspace.
@@ -933,14 +933,14 @@ mod tests {
933933
// If the option is set, keep the value from the manifest.
934934
fn update_manifest_with_inherited_workspace_package_keys(
935935
opts: &MkOptions<'_>,
936-
manifest: &mut toml_edit::Document,
936+
manifest: &mut toml_edit::DocumentMut,
937937
workspace_package_keys: &toml_edit::Table,
938938
) {
939939
if workspace_package_keys.is_empty() {
940940
return;
941941
}
942942

943-
let try_remove_and_inherit_package_key = |key: &str, manifest: &mut toml_edit::Document| {
943+
let try_remove_and_inherit_package_key = |key: &str, manifest: &mut toml_edit::DocumentMut| {
944944
let package = manifest["package"]
945945
.as_table_mut()
946946
.expect("package is a table");
@@ -974,7 +974,7 @@ fn update_manifest_with_inherited_workspace_package_keys(
974974
/// with the new package in it.
975975
fn update_manifest_with_new_member(
976976
root_manifest_path: &Path,
977-
workspace_document: &mut toml_edit::Document,
977+
workspace_document: &mut toml_edit::DocumentMut,
978978
display_path: &str,
979979
) -> CargoResult<bool> {
980980
// If the members element already exist, check if one of the patterns
@@ -1048,7 +1048,7 @@ fn get_display_path(root_manifest_path: &Path, package_path: &Path) -> CargoResu
10481048
// Check if the package can be a member of the workspace.
10491049
fn can_be_workspace_member(
10501050
display_path: &str,
1051-
workspace_document: &toml_edit::Document,
1051+
workspace_document: &toml_edit::DocumentMut,
10521052
) -> CargoResult<bool> {
10531053
if let Some(exclude) = workspace_document
10541054
.get("workspace")

src/cargo/ops/cargo_package.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -453,11 +453,10 @@ fn build_lock(ws: &Workspace<'_>, orig_pkg: &Package) -> CargoResult<String> {
453453
let orig_resolve = ops::load_pkg_lockfile(ws)?;
454454

455455
// Convert Package -> TomlManifest -> Manifest -> Package
456-
let toml_manifest = prepare_for_publish(orig_pkg.manifest().original(), ws, orig_pkg.root())?;
457-
let package_root = orig_pkg.root();
456+
let toml_manifest =
457+
prepare_for_publish(orig_pkg.manifest().resolved_toml(), ws, orig_pkg.root())?;
458458
let source_id = orig_pkg.package_id().source_id();
459-
let (manifest, _nested_paths) =
460-
to_real_manifest(toml_manifest, false, source_id, package_root, gctx)?;
459+
let manifest = to_real_manifest(toml_manifest, source_id, orig_pkg.manifest_path(), gctx)?;
461460
let new_pkg = Package::new(manifest, orig_pkg.manifest_path());
462461

463462
// Regenerate Cargo.lock using the old one as a guide.

0 commit comments

Comments
 (0)