Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(toml): Provide a way to show unused manifest keys for dependencies #11630

Merged
merged 1 commit into from
Mar 1, 2023

Conversation

Muscraft
Copy link
Member

Dependencies have not been able to show unused manifest keys for some time, this problem partially resulted in #11329.

This problem is caused by having an enum when deserializing. To get around this you can use:

#[serde(flatten)]
other: BTreeMap<String, toml::Value>,

This collects any unused keys into other that can later be used to show warnings. This idea was suggested in a thread I cannot find but is mentioned in serde#941.

@rustbot
Copy link
Collaborator

rustbot commented Jan 26, 2023

r? @ehuss

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 26, 2023
@ehuss
Copy link
Contributor

ehuss commented Jan 28, 2023

I'm a bit confused as to the full details of the situation. Some of these ignored messages work on stable or nightly, and I'd like to dig into the details of what is going on.

Starting with #11565, none of the ignored messages seem to be working. Can you explain why serde_ignored isn't handling them starting with that PR, but was working before? Which situations worked and which ones didn't? Is there something about untagged enums that doesn't work? Would it be possible to have a custom deserialize impl that avoids needing special handling here?

@Muscraft
Copy link
Member Author

Before #11565, the two tests added in this PR pass with only minor changes (location of a few messages). I believe this is due to IntermediateDependency. IntermediateDependency made it so anything that wasn't defined within it would throw an unused manifest key warning. This is expected behavior, but it wouldn't throw those warnings if what it would be turned into didn't have one of those fields. This is ultimately the root cause of #11329.

Test showing it misses `git` when using workspace inheritance
#[cargo_test]
fn warn_inherit_unused_manifest() {
    Package::new("dep", "0.1.0").publish();

    let p = project()
        .file(
            "Cargo.toml",
            r#"
            [workspace]
            members = []
            [workspace.dependencies]
            dep = { version = "0.1", wxz = "wxz" }
            [package]
            name = "bar"
            version = "0.2.0"
            authors = []
            [dependencies]
            dep = { workspace = true, git = "wxz" }
        "#,
        )
        .file("src/main.rs", "fn main() {}")
        .build();

    p.cargo("check")
        .with_stderr(
            "\
[WARNING] [CWD]/Cargo.toml: unused manifest key: workspace.dependencies.dep.wxz
[WARNING] [CWD]/Cargo.toml: unused manifest key: dependencies.dep.git
[UPDATING] `[..]` index
[DOWNLOADING] crates ...
[DOWNLOADED] dep v0.1.0 ([..])
[CHECKING] [..]
[CHECKING] bar v0.2.0 ([CWD])
[FINISHED] dev [unoptimized + debuginfo] target(s) in [..]
",
        )
        .run();
}

#11565 mostly addresses #11523 by making it so TomlDependency is just a normal TomlDependency and TomlWorkspaceDependency is opt-in. The other thing #11565 does is make things easier to read and understand, making things more unified and easier to split out in the future. The end goal with work similar to #11565 is to make toml/mod.rs easier to understand and make changes to.

As for why #11565 caused this regression/why IntermediateDependency partially worked, it is due to how serde_ignored works. Fields inside of an untagged enum are known to have problems with serde_ignored since serde must try to deserialize it into all possible formats. Since it must try all formats, things that should throw an unused manifest key warning don't.

This PR tries to fix that by using #[serde(other)], which can collect everything that would be "unused". We can then output those later. I am unsure if a custom deserialize impl would solve this issue. I would have to dig much deeper into that area to know if it is a viable solution compared to what I have already come up with.

Comment on lines 1965 to 1969
.map(|k| match k {
DepKind::Normal => "dependencies",
DepKind::Development => "dev-dependencies",
DepKind::Build => "build-dependencies",
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is duplicated code with DepTable::kind_table, could that instead be moved to a method of DepKind and reuse it?

})
.unwrap_or("dependencies");
let table_in_toml = if let Some(platform) = &cx.platform {
format!("target.{}.{kind_name}", platform.to_string())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: This doesn't handle quoting TOML keys. But it looks like stringify doesn't do that, either. Probably not too important, just wanted to note it.

@ehuss
Copy link
Contributor

ehuss commented Feb 5, 2023

Hm, that's unfortunate. It seems like this affects everything that uses MaybeWorkspace. Would it be possible to fix that, too?

I'd be reluctant to add a bunch of manual checks for ignored fields. Would it be possible to add custom deserializers for the different MaybeWorkspace kinds? For example, the string kinds can be something like:

type MaybeString = MaybeWorkspace<String, TomlWorkspaceField>;

impl<'de> de::Deserialize<'de> for MaybeString {
    fn deserialize<D>(d: D) -> Result<Self, D::Error>
    where
        D: de::Deserializer<'de>,
    {
        struct Visitor;

        impl<'de> de::Visitor<'de> for Visitor {
            type Value = MaybeString;

            fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
                f.write_str("a string or workspace")
            }

            fn visit_string<E>(self, value: String) -> Result<Self::Value, E>
            where
                E: de::Error,
            {
                Ok(MaybeString::Defined(value))
            }

            fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>
            where
                V: de::MapAccess<'de>,
            {
                let mvd = de::value::MapAccessDeserializer::new(map);
                TomlWorkspaceField::deserialize(mvd).map(MaybeWorkspace::Workspace)
            }
        }

        d.deserialize_any(Visitor)
    }
}

Then serde_ignored should work for those kinds of fields.

(I just hacked that together, it may need some work.)

The only things that will have problems are those that are maps. From what I can tell, that is just dependencies and badges. Badges might be a little complicated since they will likely need an other field, too, so they couldn't reuse TomlWorkspaceField.

That may result in more total lines of code, so I'm not 100% sure it is worth it, but it might help ensure that any fields added in the future don't forget to manually check for unused keys.

@ehuss
Copy link
Contributor

ehuss commented Feb 24, 2023

@Muscraft Just checking if you had any questions here. I'm a little concerned about the regression in diagnostics in 1.69. If a more general solution for the inherited definitions looks to be a lot of work, I'd be happy to move forward with a fix for the primary issue of ignored fields in dependency declarations, and address other cases in future PRs.

@rustbot rustbot added A-crate-dependencies Area: [dependencies] of any kind A-manifest Area: Cargo.toml issues labels Mar 1, 2023
@Muscraft
Copy link
Member Author

Muscraft commented Mar 1, 2023

It looks like I need to rebase onto master. The changes between my first commit and the one I force pushed are here

@ehuss
Copy link
Contributor

ehuss commented Mar 1, 2023

This looks great, thanks!

We discussed the unfortunate increase in lines of code here with all the serde impls. @Muscraft indicated interest in organizing things into more submodules, which sounds great to me, but they will follow up on that later.

@bors r+

@bors
Copy link
Collaborator

bors commented Mar 1, 2023

📌 Commit a32af2f has been approved by ehuss

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Mar 1, 2023
@bors
Copy link
Collaborator

bors commented Mar 1, 2023

⌛ Testing commit a32af2f with merge 0942fc7...

@bors
Copy link
Collaborator

bors commented Mar 1, 2023

☀️ Test successful - checks-actions
Approved by: ehuss
Pushing 0942fc7 to master...

@bors bors merged commit 0942fc7 into rust-lang:master Mar 1, 2023
@Muscraft Muscraft deleted the fix-unused-manifest-keys branch March 2, 2023 14:04
@weihanglo weihanglo added the beta-nominated Nominated to backport to the beta branch. label Mar 6, 2023
@weihanglo
Copy link
Member

Nominated beta backport to 1.69.

bors added a commit that referenced this pull request Mar 7, 2023
chore: Backport #11630 to `1.69.0`

#11630 was a fix for unused manifest keys not showing. It did not make it in before branching  `1.69.0`. This backports that fix so it will be in `1.69.0`

Commits:
fix(toml): Provide a way to show unused manifest keys for workspace inheritance
(cherry picked from commit a32af2f)

Ref: rust-lang/rust#108665
weihanglo added a commit to weihanglo/rust that referenced this pull request Mar 7, 2023
23 commits in 9880b408a3af50c08fab3dbf4aa2a972df71e951..c1334b059c6dcceab3c10c81413f79bb832c8d9d
2023-02-28 19:39:39 +0000 to 2023-03-07 19:21:50 +0000

- Add `CARGO_PKG_README` (rust-lang/cargo#11645)
- path dependency: fix cargo-util version (rust-lang/cargo#11807)
- Adding display of which target failed to compile (rust-lang/cargo#11636)
- Fix `CARGO_CFG_` vars for configs defined both with and without value (rust-lang/cargo#11790)
- Breaking endless loop on cyclic features in added dependency in cargo-add (rust-lang/cargo#11805)
- Enhance the doc of timing report with graphs (rust-lang/cargo#11798)
- Make `sparse` the default protocol for crates.io (rust-lang/cargo#11791)
- Use sha2 to calculate SHA256 (rust-lang/cargo#11795)
- gitoxide progress bar fixes (rust-lang/cargo#11800)
- Check publish_to_alt_registry publish content (rust-lang/cargo#11799)
- chore: fix missing files in autolabel trigger_files (rust-lang/cargo#11797)
- chore: Update base64 (rust-lang/cargo#11796)
- Fix some doc typos (rust-lang/cargo#11794)
- chore(ci): Enforce cargo-deny in CI (rust-lang/cargo#11761)
- Some cleanup for unstable docs (rust-lang/cargo#11793)
- gitoxide integration: fetch (rust-lang/cargo#11448)
- patch can conflict on not activated packages (rust-lang/cargo#11770)
- fix(toml): Provide a way to show unused manifest keys for dependencies (rust-lang/cargo#11630)
- Improve error for missing crate in --offline mode for sparse index (rust-lang/cargo#11783)
- feat(resolver): `-Zdirect-minimal-versions` (rust-lang/cargo#11688)
- feat: Use test name for dir when running tests (rust-lang/cargo#11738)
- Jobserver cleanup (rust-lang/cargo#11764)
- Fix help string for  "--charset" option of "cargo tree" (rust-lang/cargo#11785)

Note that some 3rd-party licensing allowed list changed due to the
introducion of `gix` dependency
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 8, 2023
Update cargo

25 commits in 9880b408a3af50c08fab3dbf4aa2a972df71e951..7d3033d2e59383fd76193daf9423c3d141972a7d
2023-02-28 19:39:39 +0000 to 2023-03-08 17:05:08 +0000

- Revert "rust-lang/cargo#11738" - Use test name for dir when running tests (rust-lang/cargo#11812)
- Update CHANGELOG for 1.68 backports (rust-lang/cargo#11810)
- Add `CARGO_PKG_README` (rust-lang/cargo#11645)
- path dependency: fix cargo-util version (rust-lang/cargo#11807)
- Adding display of which target failed to compile (rust-lang/cargo#11636)
- Fix `CARGO_CFG_` vars for configs defined both with and without value (rust-lang/cargo#11790)
- Breaking endless loop on cyclic features in added dependency in cargo-add (rust-lang/cargo#11805)
- Enhance the doc of timing report with graphs (rust-lang/cargo#11798)
- Make `sparse` the default protocol for crates.io (rust-lang/cargo#11791)
- Use sha2 to calculate SHA256 (rust-lang/cargo#11795)
- gitoxide progress bar fixes (rust-lang/cargo#11800)
- Check publish_to_alt_registry publish content (rust-lang/cargo#11799)
- chore: fix missing files in autolabel trigger_files (rust-lang/cargo#11797)
- chore: Update base64 (rust-lang/cargo#11796)
- Fix some doc typos (rust-lang/cargo#11794)
- chore(ci): Enforce cargo-deny in CI (rust-lang/cargo#11761)
- Some cleanup for unstable docs (rust-lang/cargo#11793)
- gitoxide integration: fetch (rust-lang/cargo#11448)
- patch can conflict on not activated packages (rust-lang/cargo#11770)
- fix(toml): Provide a way to show unused manifest keys for dependencies (rust-lang/cargo#11630)
- Improve error for missing crate in --offline mode for sparse index (rust-lang/cargo#11783)
- feat(resolver): `-Zdirect-minimal-versions` (rust-lang/cargo#11688)
- feat: Use test name for dir when running tests (rust-lang/cargo#11738)
- Jobserver cleanup (rust-lang/cargo#11764)
- Fix help string for  "--charset" option of "cargo tree" (rust-lang/cargo#11785)

---

~~This update is primarily for making rust-lang/cargo#11630 into 1.69~~ (will file a beta backport then). However, just look into the licenses and dependencies permitted list, it looks a bit unfortunate but inevitable I guess?

r? `@ehuss`
cc `@Muscraft`
@ehuss ehuss added this to the 1.70.0 milestone Mar 9, 2023
saethlin pushed a commit to saethlin/miri that referenced this pull request Mar 11, 2023
Update cargo

25 commits in 9880b408a3af50c08fab3dbf4aa2a972df71e951..7d3033d2e59383fd76193daf9423c3d141972a7d
2023-02-28 19:39:39 +0000 to 2023-03-08 17:05:08 +0000

- Revert "rust-lang/cargo#11738" - Use test name for dir when running tests (rust-lang/cargo#11812)
- Update CHANGELOG for 1.68 backports (rust-lang/cargo#11810)
- Add `CARGO_PKG_README` (rust-lang/cargo#11645)
- path dependency: fix cargo-util version (rust-lang/cargo#11807)
- Adding display of which target failed to compile (rust-lang/cargo#11636)
- Fix `CARGO_CFG_` vars for configs defined both with and without value (rust-lang/cargo#11790)
- Breaking endless loop on cyclic features in added dependency in cargo-add (rust-lang/cargo#11805)
- Enhance the doc of timing report with graphs (rust-lang/cargo#11798)
- Make `sparse` the default protocol for crates.io (rust-lang/cargo#11791)
- Use sha2 to calculate SHA256 (rust-lang/cargo#11795)
- gitoxide progress bar fixes (rust-lang/cargo#11800)
- Check publish_to_alt_registry publish content (rust-lang/cargo#11799)
- chore: fix missing files in autolabel trigger_files (rust-lang/cargo#11797)
- chore: Update base64 (rust-lang/cargo#11796)
- Fix some doc typos (rust-lang/cargo#11794)
- chore(ci): Enforce cargo-deny in CI (rust-lang/cargo#11761)
- Some cleanup for unstable docs (rust-lang/cargo#11793)
- gitoxide integration: fetch (rust-lang/cargo#11448)
- patch can conflict on not activated packages (rust-lang/cargo#11770)
- fix(toml): Provide a way to show unused manifest keys for dependencies (rust-lang/cargo#11630)
- Improve error for missing crate in --offline mode for sparse index (rust-lang/cargo#11783)
- feat(resolver): `-Zdirect-minimal-versions` (rust-lang/cargo#11688)
- feat: Use test name for dir when running tests (rust-lang/cargo#11738)
- Jobserver cleanup (rust-lang/cargo#11764)
- Fix help string for  "--charset" option of "cargo tree" (rust-lang/cargo#11785)

---

~~This update is primarily for making rust-lang/cargo#11630 into 1.69~~ (will file a beta backport then). However, just look into the licenses and dependencies permitted list, it looks a bit unfortunate but inevitable I guess?

r? `@ehuss`
cc `@Muscraft`
bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 19, 2023
…nglo

[beta-1.69] cargo beta backports

3 commits in 9880b408a3af50c08fab3dbf4aa2a972df71e951..7b18c85808a6b45ec8364bf730617b6f13e0f9f8
2023-02-28 19:39:39 +0000 to 2023-03-17 12:29:33 +0000
- [beta-1.69] backport rust-lang/cargo#11824 (rust-lang/cargo#11863)
- [beta-1.69] backport rust-lang/cargo#11820 (rust-lang/cargo#11823)
- chore: Backport rust-lang/cargo#11630 to `1.69.0` (rust-lang/cargo#11806)

r? `@ghost`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-crate-dependencies Area: [dependencies] of any kind A-manifest Area: Cargo.toml issues beta-nominated Nominated to backport to the beta branch. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants