pubgrub-rs / pubgrub

PubGrub version solving algorithm implemented in Rust
https://pubgrub-rs.github.io/pubgrub/pubgrub/
Mozilla Public License 2.0
363 stars 34 forks source link

Allow to access a `Range`'s segments #258

Open giacomocavalieri opened 5 days ago

giacomocavalieri commented 5 days ago

Hello! I ran into a problem while writing some custom error reporting for resolution failure for the Gleam compiler. What I do is I start from a DerivationTree, transform it a bit, and report a pretty printed error message showing the failing constraints along with version ranges. For example the following derivation tree:

// I'm omitting terms and ids and pretty printing the version ranges...
Derived {
  cause1: Derived {
    cause1:  FromDepOf {
      wisp: 1.1.0,
      gleam_json: 0.6.0 <= v < 2.0.0,
    },
    cause2:  FromDepOf {
      prova: 0.0.0,
      wisp: 1.1.0,
    },
  },
  cause2: FromDepOf {
    prova: 0.0.0,
    gleam_json: 2.0.0 <= v < 3.0.0,
  },
}

Gets turned into:

Unable to find compatible versions for the version constraints in your
gleam.toml:

- `prova` requires `wisp` to be `1.1.0`
- and all versions of `wisp` in that range require `gleam_json` to be
`0.6.0 <= v < 2.0.0`
- but `prova` also requires `gleam_json` to be `2.0.0 <= v < 3.0.0`
- and there is no version of `gleam_json` that satiesfies both constraints

One thing I'd like to change is the default look of version ranges once they're printed: for example having >= 2.0.0 and < 3.0.0 instead of 2.0.0 <= v < 3.0.0; this would look more familiar to a Gleam programmer since it more closely resembles how one would write a version constraint in Gleam.

My problem is that the only way I found to turn a Range<_> into a string is using the default fmt implementation and since the segments field is private I cannot roll my own pretty printing implementation for ranges. Could the package expose a way to access a range's segments?

Thank you!

zanieb commented 5 days ago

Yeah this is a bit of a rough edge. Thank you for sharing your use-case! You may find the the uv report implementation interesting and helpful — we have customized the messages quite a bit.

I think you can access a range's segments with Range::iter(), e.g., for segment in range.iter()

giacomocavalieri commented 5 days ago

You may find the the uv report implementation interesting and helpful — we have customized the messages quite a bit.

I'll have a look at it for sure, thank you!!

I think you can access a range's segments with Range::iter(), e.g., for segment in range.iter()

I'm not really that good of a Rustacean so I might be probably missing something, but it doesn't look like pubgrub::range::Range is implementing the iterator trait, if I try writing range.iter() I get:

No method named `iter` found for struct `pubgrub::range::Range` in the current scope
method not found in `Range<Version>`
zanieb commented 5 days ago

I'll have a look at it for sure, thank you!!

Be warned it's quite complicated. Happy to help though.

... but it doesn't look like pubgrub::range::Range is implementing the iterator trait...

Hm it's implemented at https://github.com/pubgrub-rs/pubgrub/blob/fe65959d72ecff9ad3a555256053d894fa697e57/src/range.rs#L835-L838

mpizenberg commented 5 days ago

One remark, it’s possible that gleam still depends on pubgrub 0.2.1 as no new version has been published since that. However, a lot has changed on the default dev branch. And uv is working from the latest code of the dev branch, not from v0.2.1. I don’t think that iterator was existing/exposed in version 0.2.1.

We do not intend to update version 0.2 of the pubgrub crate. It currently is stabilizing to a version 0.3 that would support uv features and others that @Eh2406 is working on for cargo. So my guess is you have three options @giacomocavalieri

  1. fork the v0.2.1 and add the function you need
  2. update to the current dev branch, which contains a lot of improvements, many related to error reporting. It has a slightly different api, but there should be an easy upgrade path, because in theory the new api is more expressive than the old one. So we can emulate the v0.2.1 api with the one from the dev branch
  3. wait for v0.3 to be published before updating. It can take a long time since a lot of documentation is needed.
giacomocavalieri commented 4 days ago

@mpizenberg thank you for the really helpful answer!! Ideally I'd like to wait for v0.3, do you have a rough date in mind for when we could see a release or is it going to be really far into the future?

Eh2406 commented 4 days ago

So many deadlines have passed me by, I like the sound they make when they go past, it makes me hesitant to admit to anymore. But according to the document I share with my boss I'm supposed to have the next release out by the end of the year. Though, after committing to that I instead spent my time working on #232 which has been a lot trickier to understand/diagnose than I was expecting. 🤷

If you want to see progress before the official release I may be able to help by:

konstin commented 4 days ago

I'd love to start doing alpha releases! Even if the docs aren't ready, this should get us into the process of eventually releasing 0.3.

mpizenberg commented 4 days ago

a PR to your project do the up graid to the dev branch.

whoever does that, it will be a good learning point for improving the upgrade docs. Especially if that’s not Jacob doing the upgrade.

giacomocavalieri commented 3 days ago

Thank you so much to everyone who replied! @Eh2406 thank you for being so helpful, I really appreciate it! I don't want to distract you or take any of your time, I can gladly wait for a release by the end of the year or even later, I'm in no rush :)

Alijocker369 commented 2 days ago

Hello! I ran into a problem while writing some custom error reporting for resolution failure for the Gleam compiler. What I do is I start from a DerivationTree, transform it a bit, and report a pretty printed error message showing the failing constraints along with version ranges. For example the following derivation tree:

// I'm omitting terms and ids and pretty printing the version ranges...
Derived {
  cause1: Derived {
    cause1:  FromDepOf {
      wisp: 1.1.0,
      gleam_json: 0.6.0 <= v < 2.0.0,
    },
    cause2:  FromDepOf {
      prova: 0.0.0,
      wisp: 1.1.0,
    },
  },
  cause2: FromDepOf {
    prova: 0.0.0,
    gleam_json: 2.0.0 <= v < 3.0.0,
  },
}

Gets turned into:

Unable to find compatible versions for the version constraints in your
gleam.toml:

- `prova` requires `wisp` to be `1.1.0`
- and all versions of `wisp` in that range require `gleam_json` to be
`0.6.0 <= v < 2.0.0`
- but `prova` also requires `gleam_json` to be `2.0.0 <= v < 3.0.0`
- and there is no version of `gleam_json` that satiesfies both constraints

One thing I'd like to change is the default look of version ranges once they're printed: for example having >= 2.0.0 and < 3.0.0 instead of 2.0.0 <= v < 3.0.0; this would look more familiar to a Gleam programmer since it more closely resembles how one would write a version constraint in Gleam.

My problem is that the only way I found to turn a Range<_> into a string is using the default fmt implementation and since the segments field is private I cannot roll my own pretty printing implementation for ranges. Could the package expose a way to access a range's segments?

Thank you!