-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
feat(resolver): -Zdirect-minimal-versions
#11688
Conversation
r? @weihanglo (rustbot has picked a reviewer for you, use r? to override) |
Should we decouple nightly from the other test jobs so we can at least see the rest of CI status or maybe even allow merging regardless of nightly failures? |
So if I understand the functionality right you are passing around a flag that means "for this dependency only provide 1 candidate". Then we make sure to pass that as "true" for direct dependencies and "false" for indirect dependencies. Did I understand that correctly? On a different topic, thank you for adding tests! If you've already written/added the tests for Similarly there are some tests for |
Yes, that is correct. It effectively gives us a |
One of the resolver's chronic problems is having a large number of knobs and state that need to be kept synchronized, with little in the code to teach the connections. Naively it sounds like "this dependency requirement should only ever give one candidate" should live in a |
I lean towards gathering more information before generalizing this. We have Thoughts? |
I agree that we are in a prototyping phase. I think the semantics of this new flag are reasonable as a next thing to try. All I'm wondering about is where is the best place to shoehorn in this extra |
☔ The latest upstream changes (presumably #11646) made this pull request unmergeable. Please resolve the merge conflicts. |
This is an alternative to `-Zminimal-versions` as discussed in rust-lang#5657. The problem with `-Zminimal-versions` is it requires the root most dependencies to verify it and we then percolate that up the stack. This requires a massive level of cooperation to accomplish and so far there have been mixed results with it to the point that cargo's unstable documentation discourages its use. `-Zdirect-minimal-versions` instead only applies this rule to your direct dependencies, allowing anyone in the stack to immediately adopt it, independent of everyone else. Special notes - Living up to the name and the existing design, this ignores yanked crates. This makes sense for `^1.1` version requirements but might look weird for `^1.1.1` version requirements as it could select `1.1.2`. - This will error if an indirect dependency requires a newer version. Your version requirement will need to capture what you use **and** all of you dependencies. An alternative design would have tried to merge the result of minimum versions for direct dependencies and maximum versions for indirect dependencies. This would have been complex and led to weird corner cases, making it harder to predict. I also suspect the value gained would be relatively low as you can't verify that version requirement in any other way. - The error could be improved to call out that this was from minimal versions but I felt getting this out now and starting to collect feedback was more important.
@Eh2406 as discussed, I've kept the current approach as its more surgical ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks good as a first PR for the feature.
I'd like to register two things that need to be dealt with before stabilization:
- When we know we've got the semantics correct, we must experiment with other abstractions. Only having tried alternatives would I be willing to stabilize passing around this argument.
- We need better error messages. Specifically
versions that meet the requirements
^1.1are: 1.1.0
needs to explain why1.2.0
does not match. Of course, not a blocker on initial experimentation.
src/cargo/core/resolver/dep_cache.rs
Outdated
&mut self, | ||
dep: &Dependency, | ||
first_minimal_version: bool, | ||
) -> Poll<CargoResult<Rc<Vec<Summary>>>> { | ||
if let Some(out) = self.registry_cache.get(dep).cloned() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trying to think whether we need to add first_minimal_version
to the cache key. I think we do, as it's perfectly reasonable to have a transitive and a non-transitive Dependency
but where this query returns different results.
But either adding it to the cash key or adding a comment explaining why it's not needed would be appreciated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I went with your other comment about parent.is_none()
though I hesitate about that because that is knowledge outside of the resolver.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are 2 caches here. self.registry_cache
has parent
in is cache key. Thank you for adding a comment.
But self.registry_cache
appears to me not to keep track of the fact that the result of query
may differ depending on the value of first_minimal_version
. If I've missed something please add a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
self.registry_cache
is now tracking the first_minimal_version
Hand this over to Jacob |
On a larger note... We have many levels of caching going on in the resolver. It is not clear to me that they still all pull their weight. When each one was added it was a significant performance when. But now resolver speed is not the significant bottleneck it used to be so absolute performance is less critical. Especially as I now consider the cost of code complexity as higher than I used to. But in order to decide we would need an objective and repeatable measure of the performance cost. The resolver needs an isolated benchmark. |
@bors r+ |
☀️ Test successful - checks-actions |
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
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`
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`
My understanding is that it's okay that we don't use these minimal versions directly in our normal/committed Cargo.lock file, because we may want to pick up more recent compatible versions that have addressed security issues or improved performance, etc. That said, we still want to periodically test the minimal versions to ensure that our own project still compiles and runs as expected. This will help to increase compatibility across the whole Rust ecosystem when there are shared dependencies and someone is using our library. I've also abstracted out the CUE _testRust steps here, so they can be shared. See: - rust-lang/cargo#11688 - https://users.rust-lang.org/t/psa-please-specify-precise-dependency-versions-in-cargo-toml/71277 - https://twitter.com/jonhoo/status/1571290371124260865 - cue-lang/cue#860
My understanding is that it's okay that we don't use these minimal versions directly in our normal/committed Cargo.lock file, because we may want to pick up more recent compatible versions that have addressed security issues or improved performance, etc. That said, we still want to periodically test the minimal versions to ensure that our own project still compiles and runs as expected. This will help to increase compatibility across the whole Rust ecosystem when there are shared dependencies and someone is using our library. I've also abstracted out the CUE _testRust steps here, so they can be shared. See: - rust-lang/cargo#11688 - https://doc.rust-lang.org/beta/cargo/reference/unstable.html#minimal-versions - https://users.rust-lang.org/t/psa-please-specify-precise-dependency-versions-in-cargo-toml/71277 - https://twitter.com/jonhoo/status/1571290371124260865 - cue-lang/cue#860
My understanding is that it's okay that we don't use these minimal versions directly in our normal/committed Cargo.lock file, because we may want to pick up more recent compatible versions that have addressed security issues or improved performance, etc. That said, we still want to periodically test the minimal versions to ensure that our own project still compiles and runs as expected. This will help to increase compatibility across the whole Rust ecosystem when there are shared dependencies and someone is using our library. I've also abstracted out the CUE _testRust steps here, so they can be shared. See: - rust-lang/cargo#11688 - https://doc.rust-lang.org/beta/cargo/reference/unstable.html#minimal-versions - https://users.rust-lang.org/t/psa-please-specify-precise-dependency-versions-in-cargo-toml/71277 - https://twitter.com/jonhoo/status/1571290371124260865 - cue-lang/cue#860
My understanding is that it's okay that we don't use these minimal versions directly in our normal/committed Cargo.lock file, because we may want to pick up more recent compatible versions that have addressed security issues or improved performance, etc. That said, we still want to periodically test the minimal versions to ensure that our own project still compiles and runs as expected. This will help to increase compatibility across the whole Rust ecosystem when there are shared dependencies and someone is using our library. I've also abstracted out the CUE _testRust steps here, so they can be shared. See: - rust-lang/cargo#11688 - https://doc.rust-lang.org/beta/cargo/reference/unstable.html#minimal-versions - https://users.rust-lang.org/t/psa-please-specify-precise-dependency-versions-in-cargo-toml/71277 - https://twitter.com/jonhoo/status/1571290371124260865 - cue-lang/cue#860
This is an alternative to
-Zminimal-versions
as discussed in #5657.Problems with
-Zminimal-versions
includesdocumentation discourages its use.
cargo check -Zminimal-versions
to force resolving to minimal but it doesn't as the default maximal resolve is compatible and requirescargo update -Zminimal-versions
-sys
crates without badlinks
-Zdirect-minimal-versions
instead only applies this rule to yourdirect dependencies, allowing anyone in the stack to immediately adopt
it, independent of everyone else.
Special notes
crates. This makes sense for
^1.1
version requirements but mightlook weird for
^1.1.1
version requirements as it could select1.1.2
.Your version requirement will need to capture what you use and all
of you dependencies. An alternative design would have tried to merge
the result of minimum versions for direct dependencies and maximum
versions for indirect dependencies. This would have been complex and
led to weird corner cases, making it harder to predict. I also suspect
the value gained would be relatively low as you can't verify that
version requirement in any other way.
dependencies
anddev-dependencies
are errorsversions but I felt getting this out now and starting to collect
feedback was more important.
One advantage of this approach over
-Zminimal-versions
is that it removes most of the problems that cargo-minimal-versions tried to workaround.As for the implementation, this might not be the most elegant solution but it works and we can always iterate and improve on it in the future.
bool
throughout but compensate for that by explicitly creating a variable to abstract away constantsdirect_minimal_version
when dealing with the unstable flag tofirst_minimal_version
when the concept of "direct" is lost tofirst_version
when we split off the ordering concept into a separate variabledirect_minimal_versions
are determined by whether they are the top-levelsummaries
that get past intoresolve
What does this PR try to resolve?
The primary use case is verifying version requirements to avoid depending on something newer than might be available in a dependent
For this to help the MSRV use case, the crate author must directly depend on all indirect dependencies where their latest release has too new of an MSRV but at least they can do so with the
^
operator, rather than<
and breaking the ecosystem.How should we test and review this PR?
The first two commits add tests using
-Zminimal-versions
. The commit that adds-Zdirect-minimal-versions
updates the tests, highlighting the differences in behavior.Additional information
Potential areas of conversation for stablization
Potential future work
-Zminimal-versions
cargo publish
s--verify
step to use this.Cargo.lock
which probably should also be verified.