From f2acc5a59fd52aee731445735568c2547e4ef6aa Mon Sep 17 00:00:00 2001
From: Matthieu Pizenberg <matthieu.pizenberg@gmail.com>
Date: Wed, 25 May 2022 18:07:32 +0200
Subject: [PATCH 1/5] Add an upgrade section

---
 src/SUMMARY.md          |   2 +
 src/upgrades/intro.md   |   5 ++
 src/upgrades/v02_v03.md | 110 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 117 insertions(+)
 create mode 100644 src/upgrades/intro.md
 create mode 100644 src/upgrades/v02_v03.md

diff --git a/src/SUMMARY.md b/src/SUMMARY.md
index 271451e..2c65170 100644
--- a/src/SUMMARY.md
+++ b/src/SUMMARY.md
@@ -8,6 +8,8 @@
   - [Strategical decision making in a DependencyProvider](./pubgrub_crate/strategy.md)
   - [Solution and error reporting](./pubgrub_crate/solution.md)
   - [Writing your own error reporting logic](./pubgrub_crate/custom_report.md)
+- [Upgrading from a previous version](./upgrades/intro.md)
+  - [Upgrading from v0.2 to v0.3](./upgrades/v02_v03.md)
 - [Advanced usage and limitations](./limitations/intro.md)
   - [Optional dependencies](./limitations/optional_deps.md)
   - [Allowing multiple versions of a package](./limitations/multiple_versions.md)
diff --git a/src/upgrades/intro.md b/src/upgrades/intro.md
new file mode 100644
index 0000000..4cef493
--- /dev/null
+++ b/src/upgrades/intro.md
@@ -0,0 +1,5 @@
+# Upgrading from a previous version
+
+Dealing with dependency managment, we know that dependency upgrades are painful, especially with breaking changes.
+We aim to provide meaningful breaking changes, and to help as much as possible people who want to upgrade their usage of PubGrub.
+So we will try to provide a dedicated section for breaking changes with upgrades explanations and instructions.
diff --git a/src/upgrades/v02_v03.md b/src/upgrades/v02_v03.md
new file mode 100644
index 0000000..a670e0b
--- /dev/null
+++ b/src/upgrades/v02_v03.md
@@ -0,0 +1,110 @@
+# Upgrading from v0.2 to v0.3
+
+If you encounter any issue upgrading, don't hesitate to reach out on our [Zulip stream](https://rust-lang.zulipchat.com/#narrow/stream/260232-t-cargo.2FPubGrub).
+
+Version 0.2 was the first publicly advertised version of our pubgrub crate so it was developped as a minimum viable solution with sound foundations for people to start building on it.
+For the sake of simplicity, it was however overly constraining the types for versions and version sets, making it impossible to correctly represent complex version types such as semantic versions with pre-release tags.
+The goal with version 0.3 is to give more flexibility to implementors of dependency providers, by defining a `VersionSet` trait with minimum requirements to be compatible with the PubGrub version solving algorithm.
+Our previous `Range` type is now one possible implementation of that trait when more constraints are imposed.
+The new `VersionSet` trait enables more flexible implementations, and is defined as follows.
+
+```rust
+/// Trait describing sets of versions.
+pub trait VersionSet: Debug + Display + Clone + Eq {
+    /// Version type associated with the sets manipulated.
+    type V: Debug + Display + Clone + Ord;
+
+    // Constructors
+    /// Constructor for an empty set containing no version.
+    fn empty() -> Self;
+    /// Constructor for a set containing exactly one version.
+    fn singleton(v: Self::V) -> Self;
+
+    // Operations
+    /// Compute the complement of this set.
+    fn complement(&self) -> Self;
+    /// Compute the intersection with another set.
+    fn intersection(&self, other: &Self) -> Self;
+
+    // Membership
+    /// Evaluate membership of a version in this set.
+    fn contains(&self, v: &Self::V) -> bool;
+
+    // Automatically implemented functions ###########################
+
+    /// Constructor for the set containing all versions.
+    fn full() -> Self { ... }
+
+    /// Compute the union with another set.
+    fn union(&self, other: &Self) -> Self { ... }
+}
+```
+
+One key difference is that the associate type `VersionSet::V` now only asks for an order, where previously, we explicitely asked for a minimal version, and a bump function to increment a version in the `Version` trait.
+This combined with the implementation freedom to handle sets how you want, instead of relying on our previous `Range` type gives a lot of possibilities.
+But with great power comes great responsability, meaning users have the responsability to implement their set operations correctly!
+
+## The new BoundedRange to replace the old Range
+
+Previously, the `Range<V: Version>` type was our implementation handling sets of version with efficient set operations for computing complements, intersections, and evaluating membership of versions.
+One of the main limitations of that type was the constraint that versions live in a discrete space, where one need to know exactly which version comes after any given version.
+This makes handling of pre-release tags not ergonomic since the `bump()` function had to produce the next possible pre-release.
+If cases where any character is allowed in tags, it could consist in adding the `\x00` character to the utf8 string, but as you can see that's not convenient and it does not feel right.
+
+To mitigate all this, `BoundedRange<V: Ord>` is our new default implementation of the `VersionSet` trait, provided in the pubgrub crate.
+At its heart, `BoundedRange` now stores an ordered collection of bounded intervals `( Bound<V>, Bound<V> )`.
+Our performance evaluation of this change indicates that the performance cost is negligeable when the version type is complex enough, like semantic versions, and is quite small (less than 10%) when the version type is minimalist like `u32`.
+This change brings two main advantages compared to previously:
+
+1. There is no need anymore to provide a smallest version, or a bump function for your version type.
+2. It is much more ergonomic to build pairs of inclusive bounds, or pairs of exclusive bounds.
+
+To update the usage of the `Range` type in your code should be quite straightforward.
+There has been some terminology changes, like `Range::none()` becoming `BoundedRange::empty()` and other name changes but every constructor available previously is still available now.
+In addition, we now also provide helpers to build ranges directly with Rust range bounds, so that one can use `2..=5` for example.
+
+Of course, if for any reason the provided `BoundedRange` type does not fit your constraints for handling sets of versions, you can provide your own implementation of the `VersionSet` trait thanks to the new v0.3 API.
+
+If you are specifically interested in v0.3 for dealing with pre-releases, we strongly suggest you also read the dedicated section of the guide for pre-releases.
+
+## Changes in the DependencyProvider to choose package versions
+
+One foundamental piece of flexibility of the pubgrub crate is that it deleguates all decision making to the caller in the `DependencyProvider` trait.
+
+```rust
+pub trait DependencyProvider<P: Package, V: Version> {
+    /// Given candidates, choose the next package version attempt
+    /// to continue building the solution.
+    fn choose_package_version(&self, potential_packages) -> // (package, version)
+
+    /// Retrieve the dependencies of the given package version.
+    fn get_dependencies(&self, package, version) -> // dependencies
+}
+```
+
+Previously, when choosing the next package to be added to the partial solution being built, the caller would be given a list of candidates, and it has the responsability to pick one package and version satisfying the provided candidates.
+That list of candidates typically grows everytime we encounter a new package and add its dependencies to candidates for the next choices.
+So depending on the resolution path chosen, it is possible to build a list of candidates that grows to big sizes.
+Then, every round, the caller has to work again on the whole list of candidates to pick one package version.
+There is a smarter way to tackle this problem, consisting in puting candidates in a priority queue.
+Everytime the solver encounters a new candidate, it will ask the caller to rate the priority to give for the choice of that candidate.
+Then everytime there is a choice to be made, the algorithm picks the first candidate in the priority list, and simply asks the caller to pick one version in that version set.
+
+```rust
+pub trait DependencyProvider<P: Package, V: Version> {
+    /// Compute the priority of a given package and range of versions for the solver.
+    /// When deciding which package to pick next, the solver will choose the highest priority one.
+    fn prioritize(&self, package, version_set) -> // priority
+
+    /// Given a package and version constraints, pick the next version to choose.
+    /// Can be the newest, oldest, or any thing you want depending on context.
+    fn choose_version(&self, package, version_set) -> // version
+
+    /// Retrieve the dependencies of the given package version.
+    fn get_dependencies(&self, package, version) -> // dependencies
+}
+```
+
+This new API is slightly more constraining that the old one, but it can give a significant performance boost.
+It's indeed turning a problem with complexity `N^2` (evaluating all packages at every choice) into one with complexity `N * log(N)` (inserting in a prioritized sorted list).
+If you have a situation where this API change prevents you from using pubgrub, please let us know!

From 5b8a9375e28917d7bf481b89f95d577b92c0436b Mon Sep 17 00:00:00 2001
From: Matthieu Pizenberg <matthieu.pizenberg@gmail.com>
Date: Sat, 22 Oct 2022 10:13:16 +0200
Subject: [PATCH 2/5] Fix typo

---
 src/upgrades/intro.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/upgrades/intro.md b/src/upgrades/intro.md
index 4cef493..ce390a1 100644
--- a/src/upgrades/intro.md
+++ b/src/upgrades/intro.md
@@ -1,5 +1,5 @@
 # Upgrading from a previous version
 
-Dealing with dependency managment, we know that dependency upgrades are painful, especially with breaking changes.
+Dealing with dependency management, we know that dependency upgrades are painful, especially with breaking changes.
 We aim to provide meaningful breaking changes, and to help as much as possible people who want to upgrade their usage of PubGrub.
 So we will try to provide a dedicated section for breaking changes with upgrades explanations and instructions.

From b98a2460c01f75c6db5405c72138bf723078247e Mon Sep 17 00:00:00 2001
From: Matthieu Pizenberg <matthieu.pizenberg@gmail.com>
Date: Sat, 22 Oct 2022 10:55:29 +0200
Subject: [PATCH 3/5] Rework intro of v02_v03.md

---
 src/upgrades/v02_v03.md | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/src/upgrades/v02_v03.md b/src/upgrades/v02_v03.md
index a670e0b..cb3df57 100644
--- a/src/upgrades/v02_v03.md
+++ b/src/upgrades/v02_v03.md
@@ -5,8 +5,23 @@ If you encounter any issue upgrading, don't hesitate to reach out on our [Zulip
 Version 0.2 was the first publicly advertised version of our pubgrub crate so it was developped as a minimum viable solution with sound foundations for people to start building on it.
 For the sake of simplicity, it was however overly constraining the types for versions and version sets, making it impossible to correctly represent complex version types such as semantic versions with pre-release tags.
 The goal with version 0.3 is to give more flexibility to implementors of dependency providers, by defining a `VersionSet` trait with minimum requirements to be compatible with the PubGrub version solving algorithm.
-Our previous `Range` type is now one possible implementation of that trait when more constraints are imposed.
-The new `VersionSet` trait enables more flexible implementations, and is defined as follows.
+Our previous `Range` type is now one possible implementation of that trait when more constraints are imposed, but the new `VersionSet` trait enables more flexible implementations.
+For comparison, let remind us how the v0.2 `Version` trait was defined:
+
+```rust
+/// Versions in pubgrub v0.2 have a minimal version (a "0" version)
+/// and are ordered such that every version has a next one.
+pub trait Version: Clone + Ord + Debug + Display {
+    /// Returns the lowest version.
+    fn lowest() -> Self;
+    /// Returns the next version, the smallest strictly higher version.
+    fn bump(&self) -> Self;
+}
+```
+
+In v0.3, the new trait `VersionSet` is similar to v0.2 `Range` type.
+It now has an associated `V` type for the version type, which still requires `Ord`, but we got rid of the `lowest()` and `bump()` requirements!
+In the code and documentation, we often alias `VersionSet` to `VS` so if you see `VS::V`, it refers to the associated version type.
 
 ```rust
 /// Trait describing sets of versions.
@@ -40,7 +55,6 @@ pub trait VersionSet: Debug + Display + Clone + Eq {
 }
 ```
 
-One key difference is that the associate type `VersionSet::V` now only asks for an order, where previously, we explicitely asked for a minimal version, and a bump function to increment a version in the `Version` trait.
 This combined with the implementation freedom to handle sets how you want, instead of relying on our previous `Range` type gives a lot of possibilities.
 But with great power comes great responsability, meaning users have the responsability to implement their set operations correctly!
 

From f9116ba7ad45302d52406b766c042ca22c6ad56b Mon Sep 17 00:00:00 2001
From: Matthieu Pizenberg <matthieu.pizenberg@gmail.com>
Date: Sat, 22 Oct 2022 11:57:50 +0200
Subject: [PATCH 4/5] Changes in upgrade/boundedrange section

---
 src/upgrades/v02_v03.md | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/src/upgrades/v02_v03.md b/src/upgrades/v02_v03.md
index cb3df57..8986d0f 100644
--- a/src/upgrades/v02_v03.md
+++ b/src/upgrades/v02_v03.md
@@ -63,9 +63,11 @@ But with great power comes great responsability, meaning users have the responsa
 Previously, the `Range<V: Version>` type was our implementation handling sets of version with efficient set operations for computing complements, intersections, and evaluating membership of versions.
 One of the main limitations of that type was the constraint that versions live in a discrete space, where one need to know exactly which version comes after any given version.
 This makes handling of pre-release tags not ergonomic since the `bump()` function had to produce the next possible pre-release.
-If cases where any character is allowed in tags, it could consist in adding the `\x00` character to the utf8 string, but as you can see that's not convenient and it does not feel right.
+In cases where any character is allowed in tags, it could consist in adding the `\x00` character to the utf8 string, but as you can see that's not convenient and it does not feel right.
 
-To mitigate all this, `BoundedRange<V: Ord>` is our new default implementation of the `VersionSet` trait, provided in the pubgrub crate.
+The new `VersionSet` trait helps solve this particular issue, but also makes the pubgrub API more complex.
+However, there are still users who do not need the added complexity, such as for Elm versions.
+We care about complexity, so we also now provide the `BoundedRange<V: Ord>` type, which is our new default implementation of the `VersionSet` trait.
 At its heart, `BoundedRange` now stores an ordered collection of bounded intervals `( Bound<V>, Bound<V> )`.
 Our performance evaluation of this change indicates that the performance cost is negligeable when the version type is complex enough, like semantic versions, and is quite small (less than 10%) when the version type is minimalist like `u32`.
 This change brings two main advantages compared to previously:
@@ -73,13 +75,22 @@ This change brings two main advantages compared to previously:
 1. There is no need anymore to provide a smallest version, or a bump function for your version type.
 2. It is much more ergonomic to build pairs of inclusive bounds, or pairs of exclusive bounds.
 
-To update the usage of the `Range` type in your code should be quite straightforward.
-There has been some terminology changes, like `Range::none()` becoming `BoundedRange::empty()` and other name changes but every constructor available previously is still available now.
-In addition, we now also provide helpers to build ranges directly with Rust range bounds, so that one can use `2..=5` for example.
+To illustrate (2), defining the `[v1, v2]` range was previously done with the need of a `bump()` call, since `[v1, v2]` is theoretically equivalent to `[v1, v2.bump()[` (right bound is excluded) under the v0.2 `Version` trait constraints.
 
-Of course, if for any reason the provided `BoundedRange` type does not fit your constraints for handling sets of versions, you can provide your own implementation of the `VersionSet` trait thanks to the new v0.3 API.
+```rust
+Range::between(v1, v2.bump())
+```
+
+In v0.3, you can now leverage the official [`core::ops::RangeBounds`](https://doc.rust-lang.org/core/ops/trait.RangeBounds.html) trait.
 
-If you are specifically interested in v0.3 for dealing with pre-releases, we strongly suggest you also read the dedicated section of the guide for pre-releases.
+```rust
+BoundedRange::from_range_bounds(v1..=v2)
+```
+
+To update the usage of the `Range` type in your code should be quite straightforward.
+There has been few naming changes for consistency, such as `Range::none()` becoming `BoundedRange::empty()` but every constructor previously available is still available now.
+Of course, if for any reason the provided `BoundedRange` type does not fit your constraints for handling sets of versions, you can provide your own implementation of the `VersionSet` trait thanks to the new v0.3 API.
+If you are especially interested in v0.3 for dealing with pre-releases, we strongly suggest you also read the [dedicated section of the guide for pre-releases](/limitations/prerelease_versions.md).
 
 ## Changes in the DependencyProvider to choose package versions
 

From c67bd017bd05fa660d2e6d1710a93f8a27aa861e Mon Sep 17 00:00:00 2001
From: Matthieu Pizenberg <matthieu.pizenberg@gmail.com>
Date: Sat, 22 Oct 2022 12:46:00 +0200
Subject: [PATCH 5/5] Changes in upgrade/dependencyprovider section

---
 src/upgrades/v02_v03.md | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/upgrades/v02_v03.md b/src/upgrades/v02_v03.md
index 8986d0f..ae2c158 100644
--- a/src/upgrades/v02_v03.md
+++ b/src/upgrades/v02_v03.md
@@ -94,9 +94,10 @@ If you are especially interested in v0.3 for dealing with pre-releases, we stron
 
 ## Changes in the DependencyProvider to choose package versions
 
-One foundamental piece of flexibility of the pubgrub crate is that it deleguates all decision making to the caller in the `DependencyProvider` trait.
+One fundamental piece of flexibility of the pubgrub crate is that it delegates all decision making to the caller in the `DependencyProvider` trait.
 
 ```rust
+/// v0.2 dependency provider trait
 pub trait DependencyProvider<P: Package, V: Version> {
     /// Given candidates, choose the next package version attempt
     /// to continue building the solution.
@@ -109,13 +110,14 @@ pub trait DependencyProvider<P: Package, V: Version> {
 
 Previously, when choosing the next package to be added to the partial solution being built, the caller would be given a list of candidates, and it has the responsability to pick one package and version satisfying the provided candidates.
 That list of candidates typically grows everytime we encounter a new package and add its dependencies to candidates for the next choices.
-So depending on the resolution path chosen, it is possible to build a list of candidates that grows to big sizes.
+So depending on the resolution path chosen, it is possible to build a list of candidates that grows fast.
 Then, every round, the caller has to work again on the whole list of candidates to pick one package version.
 There is a smarter way to tackle this problem, consisting in puting candidates in a priority queue.
 Everytime the solver encounters a new candidate, it will ask the caller to rate the priority to give for the choice of that candidate.
 Then everytime there is a choice to be made, the algorithm picks the first candidate in the priority list, and simply asks the caller to pick one version in that version set.
 
 ```rust
+/// v0.3 dependency provider trait
 pub trait DependencyProvider<P: Package, V: Version> {
     /// Compute the priority of a given package and range of versions for the solver.
     /// When deciding which package to pick next, the solver will choose the highest priority one.
@@ -130,6 +132,6 @@ pub trait DependencyProvider<P: Package, V: Version> {
 }
 ```
 
-This new API is slightly more constraining that the old one, but it can give a significant performance boost.
-It's indeed turning a problem with complexity `N^2` (evaluating all packages at every choice) into one with complexity `N * log(N)` (inserting in a prioritized sorted list).
+This new API is slightly more constraining than the old one, but it can give a significant performance boost.
+It's indeed turning a problem with complexity `N^2` (evaluating all potential packages at every choice) into one with complexity `N * log(N)` (inserting in a prioritized sorted list).
 If you have a situation where this API change prevents you from using pubgrub, please let us know!