Skip to content

cargo fix support for exported-private-dependencies #13095

Open

Description

@epage

Problem

rust-lang/rfcs#3516 calls for making exported-private-dependencies into an error in new editions. This means it needs to be machine-applicable so cargo fix can migrate it.

The problem is the most useful thing for a machine-applicable fix is to update Cargo.toml but rustc has no knowledge of that.

Proposed Solution

Intercept the message from rustc, before cargo fix (or the "machine applicable lints counter) sees this and add the machine-applicable content.

Notes

No response

Activity

  1. added
    C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`
    S-triageStatus: This issue is waiting on initial triage.
    S-acceptedStatus: Issue or feature is accepted, and has a team member available to help mentor or review
    on Dec 1, 2023
  2. epage commented on Dec 1, 2023

    @epage
    ContributorAuthor

    What we need is

    • lint code
    • dependency name (toml key)

    Looking at the compiler message

    {
      "reason": "compiler-message",
      "package_id": "cargo-pub-priv 0.1.0 (path+file:///home/epage/src/personal/dump/cargo-pub-priv)",
      "manifest_path": "/home/epage/src/personal/dump/cargo-pub-priv/Cargo.toml",
      "target": {
        "kind": [
          "lib"
        ],
        "crate_types": [
          "lib"
        ],
        "name": "cargo-pub-priv",
        "src_path": "/home/epage/src/personal/dump/cargo-pub-priv/src/lib.rs",
        "edition": "2021",
        "doc": true,
        "doctest": true,
        "test": true
      },
      "message": {
        "rendered": "warning: trait `FooTrait` from private dependency 'foo' in public interface\n  --> src/lib.rs:11:1\n   |\n11 | pub trait UseFoo: foo::FooTrait {}\n   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n",
        "children": [],
        "code": {
          "code": "exported_private_dependencies",
          "explanation": null
        },
        "level": "warning",
        "message": "trait `FooTrait` from private dependency 'foo' in public interface",
        "spans": [
          {
            "byte_end": 189,
            "byte_start": 158,
            "column_end": 32,
            "column_start": 1,
            "expansion": null,
            "file_name": "src/lib.rs",
            "is_primary": true,
            "label": null,
            "line_end": 11,
            "line_start": 11,
            "suggested_replacement": null,
            "suggestion_applicability": null,
            "text": [
              {
                "highlight_end": 32,
                "highlight_start": 1,
                "text": "pub trait UseFoo: foo::FooTrait {}"
              }
            ]
          }
        ]
      }
    }

    We have the code but not the dependency name. It'd be ugly and brittle but we could parse the dependency name out of "from private dependency '{name}' in public interface". We ship with rustc so we can make sure this stays up to date as rustc changes, though it'll cause CI failures.

    Expectation

    • Parse the json blob, ensuring its a message and has the right code, extracting the dependency name, and constructing a machine applicable lint.
      • Depending on how replacements are encoded, we might need to add an item to children
    • Test to verify we can auto-fix code
    • Test the above with dependency renames
    • Test that the "run cargo fix" message shows up for these with cargo check.
  3. removed
    S-triageStatus: This issue is waiting on initial triage.
    on Dec 1, 2023
  4. epage commented on Dec 1, 2023

    @epage
    ContributorAuthor

    Depending on the details, we might need #13096

  5. linyihai commented on Jan 2, 2024

    @linyihai
    Contributor

    Is it currently not supported to obtain the specific line number of a certain configuration item?
    Give a example, I like to know the line of license and regex in the Cargo.toml.

    image

    It looks like this issue need this ability to fixed.

    And some discussiton can be found in zulip is it possible to include position data for cargo metadata

  6. epage commented on Jan 2, 2024

    @epage
    ContributorAuthor

    @Muscraft was going to add code to cargo to get the needed spans in a follow up to #13172. If you need it before, reach out to them for notes they have on the topic

  7. linyihai commented on Jan 12, 2024

    @linyihai
    Contributor

    @Muscraft was going to add code to cargo to get the needed spans in a follow up to #13172. If you need it before, reach out to them for notes they have on the topic

    #13172 was merged recently. I'd to take a shot :-) .

  8. epage commented on Jan 12, 2024

    @epage
    ContributorAuthor

    Note that I was referring to a PR they'll be working on after that PR. That PR doesn't have the functionality you would need.

  9. iepathos commented on Jan 11, 2026

    @iepathos
    Contributor

    Hi, I'm interested in working on this.

    My current understanding of the approach to take based on the comments:

    1. Parse compiler JSON output to identify exported_private_dependencies lint codes
    2. Extract the dependency name by parsing the message text (from private dependency '{name}')
    3. Construct machine-applicable suggestions to modify Cargo.toml

    Does this align with what you had in mind?

  10. epage commented on Jan 12, 2026

    @epage
    ContributorAuthor

    Along with tests and ideally following the commit practices for tests at https://doc.crates.io/contrib/process/working-on-cargo.html#submitting-a-pull-request

  11. epage commented on Aug 10, 2026

    @epage
    ContributorAuthor

    Being machine applicable means that we always fix it which should only happen if it is definitively the right answer.

    Is it?

    If I have a impl From<foreign::ForeignError> for MyError accidentally, is the fix to make foreign public or to remove the impl? If removing the impl is a considered a breaking change, then there is only one answer. However, we could consider this more like `#[doc(hidden)]`` where the answer is "it depends".

    Some additional options

    • We never move this to an error
    • We give this a long time as a warning, greatly reducing the impact of this being an error or maybe even being machine applicable
  12. added
    S-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.
    and removed
    S-acceptedStatus: Issue or feature is accepted, and has a team member available to help mentor or review
    on Aug 10, 2026
  13. mladedav commented on Aug 26, 2026

    @mladedav
    Contributor

    My 2c: I think making the dependencies public is the simplest both from Cargo's and the user's point of view - after the fix, they can (and should) audit their public dependencies and make private again whatever they want and then change the code based on what lints are emitted then. I would expect most crates to just accept what is public though and maybe later working on trimming that down.

    I believe all instances where there was a dependency in public interface and we remove it from there, is a breaking change, so making everything in the public interface public is the only correct solution I see. If there were such cases and were automatically identifiable, the lint shouldn't fire there either. So I believe making the dependency public is definitively the right answer but the human also has a choice to evolve their API to remove the public dependency from there. Which strictly speaking they should do with a major bump, but as always, it's their choice.

    At the end of the day, the fix as currently proposed just surfaces the current state, it doesn't add anything to the public API that wasn't there to begin with.

    Ignoring/allowing/deleting specific implementations is something that only the user can do I think. If they decide to ignore a given impl because no one should use it, they can do that, but there's not way for anyone else to decide that I think.

    I think it would be beneficial for this to be machine applicable even if it is a warning but I agree there is no rush to make this an error.

  14. epage commented on Aug 26, 2026

    @epage
    ContributorAuthor

    From my understanding, the compiler has different categories of fixes. "MachineApplicable" is if it is a definitive fix that can be applied without intervention. There are also "MaybeApplicable" which cargo fix does not apply today. What you are describing sounds like MaybeApplicable. I'd love for cargo fix to have an interactive mode where we can ask the user about MaybeApplicable but we are not there today.

  15. mladedav commented on Aug 27, 2026

    @mladedav
    Contributor

    I might have described it poorly, but reading the definitions, I do think making the dependencies public in Cargo.toml is MachineApplicable. The dependencies are already part of the public API and the fix just surfaces that into Cargo.toml without any semantic changes.

    To me that's similar to e.g. how in 2024 edition, if let was changed to match because of earlier drops and people then manually verified and changed it back if they wanted to.

    We provide a fix that keeps all semantics and if users decide their original intent was different from the current state, they make manual changes afterwards.

  16. cjc0013 commented on Oct 20, 2026

    @cjc0013
  17. weihanglo commented on Oct 21, 2026

    @weihanglo
    Member

    @cjc0013 I folded your comment because it seems to be a LLM generated one. Per our policy comment should not be initially LLM generated: https://forge.rust-lang.org/policies/llm-usage.html.

    You are welcome to comment with your own voice.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`Command-fixS-needs-designStatus: Needs someone to work further on the design for the feature or fix. NOT YET accepted.Z-public-dependencyNightly: public-dependency

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions