-
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
part of the infrastructure for public & private dependencies in the resolver #6653
Conversation
r? @dwijnand (rust_highfive has picked a reviewer for you, use r? to override) |
Push a fix for my braking every test. |
src/cargo/core/resolver/context.rs
Outdated
@@ -26,6 +26,12 @@ pub struct Context { | |||
pub activations: Activations, | |||
pub resolve_features: im_rc::HashMap<PackageId, Rc<HashSet<InternedString>>>, | |||
pub links: im_rc::HashMap<InternedString, PackageId>, | |||
pub public_dependency: | |||
im_rc::HashMap<PackageId, im_rc::HashMap<InternedString, (PackageId, bool)>>, |
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.
We should probably already have this for all the other fields but could a comment be added here for this new field about what this is a map to/from?
|
||
// This is somewhat redundant with the `resolve_graph` that stores the same data, | ||
// but for querying in the opposite order. | ||
pub parents: Graph<PackageId, Rc<Vec<Dependency>>>, |
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.
In our past debugging we've found that cloning a Context
happens so often that an expensive clone means a slower resolver, so I was curious about this!
I think we explicitly removed Graph
from this data structure earlier in favor of RcList
below, so was curious on your thoughts on this.
I haven't read the whole patch yet though, so I'll likely find what happens soon.
src/cargo/core/resolver/mod.rs
Outdated
.iter() | ||
.flat_map(|x| x.values()) | ||
.filter_map(|x| if x.1 { Some(&x.0) } else { None }) | ||
.chain(Some(candidate.summary.package_id()).iter()) |
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.
The trailing .iter()
here I think can be removed
@@ -591,6 +596,44 @@ fn activate( | |||
candidate.summary.package_id(), | |||
dep.clone(), | |||
)); | |||
Rc::make_mut( |
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.
Could a comment be added here to explain what's going on?
src/cargo/core/resolver/mod.rs
Outdated
@@ -725,6 +769,30 @@ impl RemainingCandidates { | |||
continue; | |||
} | |||
} | |||
for &t in cx |
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.
Could a comment be added here abot what candidates this is rejecting?
@@ -799,6 +868,9 @@ fn find_candidate( | |||
// make any progress. As a result if we hit this condition we can | |||
// completely skip this backtrack frame and move on to the next. | |||
if !backtracked | |||
&& !conflicting_activations | |||
.values() | |||
.any(|c| *c == ConflictReason::PublicDependency) |
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.
Could the comment be updated to account for this new clause?
use im_rc; | ||
|
||
pub struct Graph<N: Clone, E: Clone> { | ||
nodes: im_rc::OrdMap<N, im_rc::OrdMap<N, E>>, |
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.
aha, I see how this would make things a bit speedier on the cloning half of things
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.
(maybe RcList
is now obsoleted?)
I added comments, I think it addresses your concerns. The test point out that the RFC did not discuss how this interacts with the other things cargo can do. I don't have a mental model of how this should work. |
So the specific questions are: How does this interact with renamed dependencies?There are lots of juicy corner cases here. On one had being able to depend on 2 different versions of the same library is one of the points of renamed dependencies. Fore example so you can publicly derive This makes my head hurt, is there something simple I am missing? If not, where is the appropriate place to discuss fundamental problems with an accepted RFC? How does this interact with
|
I got test to pass by just making deps that have a cfg or a rename invisible. This is not a sablizable solution, but it does get the test to pass. |
☔ The latest upstream changes (presumably #6687) made this pull request unmergeable. Please resolve the merge conflicts. |
src/cargo/core/resolver/mod.rs
Outdated
// other functionality is used. | ||
// TODO: this disable is not a long term solution. | ||
// This needs to be removed before public dependencies are stabilized! | ||
if dep.platform().is_none() && dep.explicit_name_in_toml().is_none() { |
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 think the behavior that we want is to probably just delete this if
clause and unconditionally run the below?
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.
Yes, we would like to delete this if statement and have the code below deal with the special handling of these corner cases. At the beginning of this PR we did not have this if statement and it broke the existing tests. Until we figure out how the corner cases are supposed to be handled, this if statement lets other people make progress.
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.
Er sorry it's taking me awhile to get back to this, but do you have a corner case in mind that this is needed for? I can't actually think of a case where the platform and/or renaming would cause issues
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.
It is easy to find the examples, just look at the test that do not pass without it.
- renaming: this test means that
foo
can seebar 0.1.0
andbar 0.2.0
.foo
can getexpected bar::Thing but got bar::Thing
errores so is not permitted by public & private dependencies. - platform: this test means that
foo
can seebar 0.1.0
andbar 0.2.0
depending on platform. This should not be a problem, but requires a deep level of disjointness analysis about platforms to be added to make it work.
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.
For renaming though we want to give an error in that case, so renaming doesn't affect public/private, right? For platforms it's true that in theory we want to take the exhaustive list of any platforms and if none of them actually activate both dependencies we don't give an error, but it seems that for all practical purposes we'd want to give an error assuming all dependencies can be activated on at least one platform.
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.
That is a reasonable position. (although different from what you suggested at #6129 (comment)) It would mean that this existing stable behavior should not be allowed. Such a decision would require more discussion. I thought that we could have that discussion in a follow up PR if that is the behavior we decide on.
This PR is the minimum functionality to unlock further work. I thought it would be more in kind for this PR to adopt the behavior of treating cfg
and rename
as having the "escape hatch" you suggested.
Do you think that we'll need to have fast paths for no public dependencies to preserve the current performance of the resolver? Or do the new code paths largely come out in the wash in profiling? |
Sorry for the delay in replying, real life is being very difficult at the moment. From what I have seen, this is not a hotspot. I have mostly been investigating cases of exponential blowout caused by this feature, and even there this inefficient code is not hot. I think with the use of Im-rs the general performance regression will will not be significant in absolute terms. That being said if you would like to check servo and x.py, it can't hurt. |
Life has been kicking me this week, and will be for the foreseeable future. I found 2 mins to rebase this. I think let's get this landed and fix the problems in follow up PRs. |
partial removal of 8052d756aa97efac332cefcf1c5d98871b43f1bd
src/cargo/core/resolver/mod.rs
Outdated
.chain(&Some(candidate_pid)) | ||
.cloned() | ||
.collect(); | ||
for c in cs { |
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.
Could the documentation for this loop and the cs
variable above be expanded to include what they're doing?
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.
Added documentation for the cs
variable. Now that I am typing a response I see that you wanted an explanation of the entire loop. BRB.
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.
Comments updated more fully. Eventually this should probably be a dedicated data structure that keeps the related functionality together, and removes some of the duplication.
@bors: r+ Looks great to me! |
📌 Commit 12e474b has been approved by |
⌛ Testing commit 12e474b with merge 0add586e3344f141b623ac1043b42321a3932de0... |
💔 Test failed - checks-travis |
@bors: retry |
⌛ Testing commit 12e474b with merge 2eb879bf7babc89dc3c32e47c547f0ef06902c34... |
💔 Test failed - checks-travis |
@bors: retry |
part of the infrastructure for public & private dependencies in the resolver This is part of my work on public & private dependencies in the resolver from #6129. As discussed there the proptest fuzzers are happy to find exponential blow up with all the back jumping strategies I have tried. So this PR does not have a back jumping strategie nor does it have the proptest fuzzers generating public dependencies. These will both need to change for the feature to stabilize. In the meantime it gives the correct results on the cases it can handle. With rust-lang/rust#57586 landed there is a lot of work to do on Cargos front end. Adding a UI for this, passing the relevant things to rustc, passing it to crates.io, passing it to cargo-metadata. This is good enough to allow that work to proceed.
☀️ Test successful - checks-travis, status-appveyor |
Update cargo, rls, books ## cargo 10 commits in 5c6aa46e6f28661270979696e7b4c2f0dff8628f..95b45eca19ac785263fed98ecefe540bb47337ac 2019-02-22 19:32:35 +0000 to 2019-03-06 19:24:30 +0000 - Relax some rustdoc tests. (rust-lang/cargo#6721) - Include build script execution in the fingerprint. (rust-lang/cargo#6720) - part of the infrastructure for public & private dependencies in the resolver (rust-lang/cargo#6653) - Bump to 0.36.0 (rust-lang/cargo#6718) - Some test/bench-related tweaks (rust-lang/cargo#6707) - Fix links to the permanent home of the edition guide. (rust-lang/cargo#6703) - HTTPS all the things (rust-lang/cargo#6614) - Cargo test quicker by not building untested examples when filtered (rust-lang/cargo#6683) - Link from ARCHITECTURE.md to docs.rs and github (rust-lang/cargo#6695) - Update how to install rustfmt (rust-lang/cargo#6696) ## rls 9 commits in 0d6f53e1a4adbaf7d83cdc0cb54720203fcb522e..6a1b5a9cfda2ae19372e0613e76ebefba36edcf5 2019-02-14 07:52:15 +0000 to 2019-03-04 20:24:45 +0000 - Update cargo and clippy. (rust-lang/rls#1388) - catch up rust-lang/rust PR#58321 (rust-lang/rls#1384) - Apply Clippy fixes (rust-lang/rls#1327) - Various cosmetic improvements (rust-lang/rls#1326) - Make test `RlsHandle` transport-agnostic (rust-lang/rls#1317) - Translate remaining tests (rust-lang/rls#1320) - Remove unnecessary #![feature]s (rust-lang/rls#1323) - Update Clippy (rust-lang/rls#1319) - Update Clippy (rust-lang/rls#1315) cc @Xanewok ## Books See #58936 for details.
This was supposed to be in rust-lang#6653, but was lost in the edits of history. Reconstructed from 5522aba
add public & private prop tests. This is the code that checks that the resolver does not output a public & private conflict. We still do not have the gen of public dependencies do to 9b8b12c, because backtracking is to inefficient, but this checks that we are getting a correct answer. This was supposed to be in #6653, but was lost in the edits of history. Reconstructed from Eh2406@5522aba
This is part of my work on public & private dependencies in the resolver from #6129. As discussed there the proptest fuzzers are happy to find exponential blow up with all the back jumping strategies I have tried. So this PR does not have a back jumping strategie nor does it have the proptest fuzzers generating public dependencies. These will both need to change for the feature to stabilize. In the meantime it gives the correct results on the cases it can handle.
With rust-lang/rust#57586 landed there is a lot of work to do on Cargos front end. Adding a UI for this, passing the relevant things to rustc, passing it to crates.io, passing it to cargo-metadata. This is good enough to allow that work to proceed.