rfcs
rfcs copied to clipboard
`recommended-bin-packages` field in `Cargo.toml`
This RFC proposes the addition of an optional recommended-bin-packages field to the [package] section of Cargo.toml, to enable package authors to point out related binary packages in the error message Cargo users get when attempting to cargo install a package without binaries.
(Opening an RFC for this since the idea has gotten positive feedback on the Rust Internals forum).
Clippy could gain a lint to check that the referenced crates actually exist, have not been yanked and are actually binary crates.
I feel like this might be something that cargo publish should could/should check, at least partially, though I'd be fine to still keep it only as a future possibility.
Right, I did also think about that. The issue with that is that there's somewhat of a chicken-and-egg problem when first publishing crates since the crates referenced via this new field are likely to depend on the crate containing the field.
But if you have not published a foobar-cli crate yet, publishing foobar library crate with a recommendation for foobar-cli is bad, too. Anyone could publish a crate called foobar-cli at that point, before you publish it yourself. It seems highly advisable to me to go about this in a different order, even if doing so would involve pre-publishing a crate in a dummy state to reserve the name. Either that, or have the initial version of foobar not come with a recommended-bin-crates field. And lastly, it’s always possible to disable checks done locally on your machine by cargo publish (e.g. with --no-verify), if you know what you’re doing and you are willing to risk the race-condition and the possibility to make a mistake.
So, I personally feel like this feature is almost too restrictive for binary crates, and would make more sense as a general recommendation mechanism. For example, serde-json is often used with serde, and the serde crate could vouch for that crate being recommended.
Except this almost approaches the point where it's maybe not a good thing to include in the cargo manifest, since that is pinned to versions and for example, installing an old version of serde would give old recommendations.
Just a few thoughts on this; not super strong on these ideas, just kind of my gut reaction to the RFC.
The proposed field has to be specific to binary crates so that cargo install can point out these crates when an installation fails because the crate doesn't contain any binaries. Improving that error message is very much the primary goal of this RFC.
I don't really see the need for a more general recommendation mechanism, I think documenting related libraries in the README works well enough, for instance the second link of the serde README is Data formats supported by Serde.
I saw other people using cargo install this way,
cargo install foo-cli
alias dora='foo-cli'
foo --help
so I thought I could add a feature: if a user wants to install a foo binary, cargo can install foo-cli directly and the user can run it as foo
if a user wants to install a foo binary, cargo can install foo-cli directly and the user can run it as foo
The latter is already possible, the binary name does not have to match the package name (a package may also include multiple binaries), either by putting the main at src/bin/foo/main.rs and relying on auto-detection, or manually configuring the name separately:
[package]
name = "foo-cli"
[[bin]]
name = "foo"
path = "src/main.rs"
A random way of re-framing this is for Cargo to have an equivalent of the diagnostic namespace.
We discussed this in today's Cargo team meeting as part of our RFC triage. We had previously discussed the trade offs between putting everything into a package vs using a workspace. We are overall in favor of improving the workflow for people.
The main concern is over what schema to use (which different designs can lead to minor tweaks to the semantics). We discussed the possibility of a [diagnostics] table (inspired by the recently stabilized diagnostics attribute) and lean towards it after exploring several potential use cases for it. We'd recommend exploring what the experience would be like to create a [diagnostics] table, what kind of fields make sense within that and what lessons we should learn from the diagnostic attribute (CC @estebank for any insight you can provide).
@rfcbot merge
@rfcbot concern schema
Team member @epage has proposed to merge this. The next step is review by the rest of the tagged team members:
- [x] @Eh2406
- [x] @Muscraft
- [x] @arlosi
- [x] @ehuss
- [x] @epage
- [x] @joshtriplett
- [x] @weihanglo
Concerns:
- schema (https://github.com/rust-lang/rfcs/pull/3383#issuecomment-2135594569)
Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!
See this document for info about what commands tagged team members can give me.
@epage (off the cuff) one thing that came up with #[diagnostic] is the need for it to be very permissive without causing errors: whenever you add a feature you would never be able to remove it without pain, and if you add a new feature to one version and people want to use it, you're forcing crate authors to bump their MSRV sorely for better errors. You'll also need to see how you handle these for transitive dependencies, whether crate authors can customize errors not just for people who have added them as direct dependencies, or for everyone that has them as a dependency in their tree.
@estebank any lessons on the reporting side? We're wondering whether to expose just a string or go all out like diagnostics or have special built fields so we have semantic information.
Rather than treating this purely as diagnostic, what if we treated it as directly actionable metadata? If someone tries to install a crate, and it isn't installable because it's a library crate, and it has this field, directly install the mentioned crate instead.
We can decide that exact behavior later, but if we might want that behavior, then it doesn't seem like this belongs under a diagnostic namespace.
@joshtriplett I'd have to dig through our notes to fully remember why we were leaning towards diagnostics but one concern with this RFC as a whole is that we need to match the behavior with expectations in a way that avoids the expectations that would lead to creating a circular dependency between the library and the bin.
@epage Not following how this would go circular. It would only lead cargo from attempting to install the lib to actually installing the bin, and installing the bin would likely depend on the lib, but that's not circular. What's the scenario of concern?
(Not looking to retread a discussion that has already taken place, if this already has. I don't recall this aspect of the topic arising, though.)
@epage This is labeled as waiting-on-author ... can I do anything?
From https://github.com/rust-lang/rfcs/pull/3383#issuecomment-2135594569
We'd recommend exploring what the experience would be like to create a [diagnostics] table, what kind of fields make sense within that and what lessons we should learn from the diagnostic attribute (CC @estebank for any insight you can provide).
@joshtriplett
@epage Not following how this would go circular. It would only lead cargo from attempting to install the lib to actually installing the bin, and installing the bin would likely depend on the lib, but that's not circular. What's the scenario of concern?
(Not looking to retread a discussion that has already taken place, if this already has. I don't recall this aspect of the topic arising, though.)
This has a package referencing the package that depends on it. Do we validate the package exists? What about on first publish, do you have to double-publish? Does installing a specific version of the library imply a specific version of the binary and how do we ensure that version exists when the binary is published after?
@epage I was thinking of it as a hint, which doesn't need validating.
And I don't think it needs versioning.
@epage I was thinking of it as a hint, which doesn't need validating.
And I don't think it needs versioning.
To be clear, we are talking about
what if we treated it as directly actionable metadata? If someone tries to install a crate, and it isn't installable because it's a library crate, and it has this field, directly install the mentioned crate instead.
So looking at what a user might do
$ cargo install typos
... starts installing latest typos-cli
$ cargo install [email protected] # actual version
... starts installing latest typos-cli
$ cargo install [email protected] # mixed up and specified typos-cli version
... starts installing latest typos-cli
I think it would be wrong in the last two cases for us to install the latest version. Any warning we give will likely be lost in the sea of compilation messages (until we can get rust-lang/cargo#8889).
@epage Installing the latest version doesn't seem worse than completely failing. Or, alternatively, we could skip automatically using recommended-bin-packages if you specify an @version, and instead fail with an error that mentions the value of recommended-bin-packages instead.
@epage Installing the latest version doesn't seem worse than completely failing.
In my opinion, it is worse. The user made a specific choice and we are instead doing something arbitrary. If we warn about it, the message is most likely to be lost in the noise and they user will be subject to another long build
Or, alternatively, we could skip automatically using recommended-bin-packages if you specify an @version, and instead fail with an error that mentions the value of recommended-bin-packages instead.
Maybe, depends on the overall experience and possible surprises. It might help for someone to enumerate the different combinations and what the behavior would be (including user output). From a framing perspective, I could see this being similar to cargo add translating between _ / -, depending on the users input and the package's actual name.