Allow conflicting locals when forking#5104
Conversation
20a0b92 to
0c7ce71
Compare
0c7ce71 to
8dffb13
Compare
| /// requirement or constraint for the same package that has a URL. | ||
| pub(crate) url: Option<VerbatimParsedUrl>, | ||
| /// The local version for this requirement, if specified. | ||
| pub(crate) local: Option<Version>, |
There was a problem hiding this comment.
Is it true that if local is Some, then Version::is_local will always be true?
If so, then perhaps this could just be a Version, and case analysis uses Version::is_local or Version::local.
There was a problem hiding this comment.
After reading through the PR, I retract my suggestion. I see how this is very convenient because the acquisition of a local-only Version is pretty naturally expressed via Option<Version>. And I don't think you ever look at a local and try to access its local segments, so there isn't really any redundant case analysis.
There was a problem hiding this comment.
Is it true that if local is Some, then Version::is_local will always be true?
This is actually not true, because we also extract local versions from direct URL/path requirements.
| # via torch | ||
| torch==2.0.0+cpu ; platform_machine != 'x86_64' | ||
| # via -r requirements.in | ||
| torch==2.0.0+cu118 ; platform_machine == 'x86_64' |
## Summary This fixes a few bugs introduced by #5104. I previously thought we could track conflicting locals the same way we track conflicting URLs in forks, but it turns out that ends up being very tricky. URL forks work because we prioritize directly URL requirements. We can't prioritize locals in the same way without conflicting with the URL prioritization (this may be possible but it's not trivial), so we run into issues where a correct resolution depends on the order in which dependencies are traversed. Instead, we track local versions across all forks in `Locals`. When applying a local version, we apply all locals with markers that intersect with the current fork. This way we end up applying some local versions without creating a fork. For example, given: ``` // pyproject.toml dependencies = [ "torch==2.0.0+cu118 ; platform_machine == 'x86_64'", ] // requirements.in torch==2.0.0 . ``` We choose `2.0.0+cu118` in all cases. However, if a disjoint fork is created based on local versions, the resolver will choose the most compatible local when it narrows to a specific fork. Thus we correctly respect local versions when forking: ``` // pyproject.toml dependencies = [ "torch==2.0.0+cu118 ; platform_machine == 'x86_64'", "torch==2.0.0+cpu ; platform_machine != 'x86_64'" ] // requirements.in torch==2.0.0 . ``` We should also be able to use a similar strategy for #5150. ## Test Plan This fixes #5220 locally for me, as well as a few other bugs that were not reported yet.
Summary
Currently, the
Localstype relies on there being a single local version for a given package. With marker expressions this may not be true, a similar problem to #4435. This changes theLocalstype toForkLocals, which tracks locals for a given fork. Local versions are now tracked onPubGrubRequirementbefore forking.Resolves #4580.