diff --git a/Cargo.lock b/Cargo.lock index 796a23922..3ab2087eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2287,6 +2287,7 @@ dependencies = [ [[package]] name = "pubgrub" version = "0.2.1" +source = "git+https://github.com/zanieb/pubgrub?rev=46f1214fe6b7886709a35d8d2f2c0e1b56433b26#46f1214fe6b7886709a35d8d2f2c0e1b56433b26" dependencies = [ "indexmap 2.1.0", "log", diff --git a/Cargo.toml b/Cargo.toml index 8c07658fb..2787fb9cb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,5 @@ [workspace] members = ["crates/*"] -exclude = ["vendor/pubgrub"] resolver = "2" [workspace.package] @@ -49,6 +48,7 @@ once_cell = { version = "1.18.0" } petgraph = { version = "0.6.4" } platform-info = { version = "2.0.2" } plist = { version = "1.6.0" } +pubgrub = { git = "https://github.com/zanieb/pubgrub", rev = "46f1214fe6b7886709a35d8d2f2c0e1b56433b26" } pyproject-toml = { version = "0.8.0" } rand = { version = "0.8.5" } rayon = { version = "1.8.0" } diff --git a/crates/puffin-cli/Cargo.toml b/crates/puffin-cli/Cargo.toml index d25855f9f..bb838bef9 100644 --- a/crates/puffin-cli/Cargo.toml +++ b/crates/puffin-cli/Cargo.toml @@ -20,7 +20,6 @@ pep440_rs = { path = "../pep440-rs" } pep508_rs = { path = "../pep508-rs" } platform-host = { path = "../platform-host" } platform-tags = { path = "../platform-tags" } -pubgrub = { path = "../../vendor/pubgrub" } puffin-client = { path = "../puffin-client" } puffin-dispatch = { path = "../puffin-dispatch" } puffin-distribution = { path = "../puffin-distribution" } @@ -45,6 +44,7 @@ futures = { workspace = true } indicatif = { workspace = true } itertools = { workspace = true } miette = { workspace = true, features = ["fancy"] } +pubgrub = { workspace = true } pyproject-toml = { workspace = true } tempfile = { workspace = true } thiserror = { workspace = true } diff --git a/crates/puffin-resolver/Cargo.toml b/crates/puffin-resolver/Cargo.toml index d6b554e3d..270257c34 100644 --- a/crates/puffin-resolver/Cargo.toml +++ b/crates/puffin-resolver/Cargo.toml @@ -16,7 +16,6 @@ pep440_rs = { path = "../pep440-rs" } pep508_rs = { path = "../pep508-rs" } platform-host = { path = "../platform-host" } platform-tags = { path = "../platform-tags" } -pubgrub = { path = "../../vendor/pubgrub" } puffin-cache = { path = "../puffin-cache" } puffin-client = { path = "../puffin-client" } puffin-distribution = { path = "../puffin-distribution" } @@ -37,6 +36,7 @@ fxhash = { workspace = true } itertools = { workspace = true } once_cell = { workspace = true } petgraph = { workspace = true } +pubgrub = { workspace = true } tempfile = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } diff --git a/vendor/pubgrub/CHANGELOG.md b/vendor/pubgrub/CHANGELOG.md deleted file mode 100644 index abe44da9d..000000000 --- a/vendor/pubgrub/CHANGELOG.md +++ /dev/null @@ -1,170 +0,0 @@ -# Changelog - -All notable changes to this project will be documented in this file. - -## Unreleased [(diff)][unreleased-diff] - -## [0.2.1] - 2021-06-30 - [(diff with 0.2.0)][0.2.0-diff] - -This release is focused on performance improvements and code readability, without any change to the public API. - -The code tends to be simpler around tricky parts of the algorithm such as conflict resolution. -Some data structures have been rewritten (with no unsafe) to lower memory usage. -Depending on scenarios, version 0.2.1 is 3 to 8 times faster than 0.2.0. -As an example, solving all elm package versions existing went from 580ms to 175ms on my laptop. -While solving a specific subset of packages from crates.io went from 2.5s to 320ms on my laptop. - -Below are listed all the important changes in the internal parts of the API. - -#### Added - -- New `SmallVec` data structure (with no unsafe) using fixed size arrays for up to 2 entries. -- New `SmallMap` data structure (with no unsafe) using fixed size arrays for up to 2 entries. -- New `Arena` data structure (with no unsafe) backed by a `Vec` and indexed with `Id` where `T` is phantom data. - -#### Changed - -- Updated the `large_case` benchmark to run with both u16 and string package identifiers in registries. -- Use the new `Arena` for the incompatibility store, and use its `Id` identifiers to reference incompatibilities instead of full owned copies in the `incompatibilities` field of the solver `State`. -- Save satisfier indices of each package involved in an incompatibility when looking for its satisfier. This speeds up the search for the previous satisfier. -- Early unit propagation loop restart at the first conflict found instead of continuing evaluation for the current package. -- Index incompatibilities by package in a hash map instead of using a vec. -- Keep track of already contradicted incompatibilities in a `Set` until the next backtrack to speed up unit propagation. -- Unify `history` and `memory` in `partial_solution` under a unique hash map indexed by packages. This should speed up access to relevan terms in conflict resolution. - -## [0.2.0] - 2020-11-19 - [(diff with 0.1.0)][0.1.0-diff] - -This release brings many important improvements to PubGrub. -The gist of it is: - -- A bug in the algorithm's implementation was [fixed](https://github.com/pubgrub-rs/pubgrub/pull/23). -- The solver is now implemented in a `resolve` function taking as argument - an implementer of the `DependencyProvider` trait, - which has more control over the decision making process. -- End-to-end property testing of large synthetic registries was added. -- More than 10x performance improvement. - -### Changes affecting the public API - -#### Added - -- Links to code items in the code documentation. -- New `"serde"` feature that allows serializing some library types, useful for making simple reproducible bug reports. -- New variants for `error::PubGrubError` which are `DependencyOnTheEmptySet`, - `SelfDependency`, `ErrorChoosingPackageVersion` and `ErrorInShouldCancel`. -- New `type_alias::Map` defined as `rustc_hash::FxHashMap`. -- New `type_alias::SelectedDependencies` defined as `Map`. -- The types `Dependencies` and `DependencyConstraints` were introduced to clarify intent. -- New function `choose_package_with_fewest_versions` to help implement - the `choose_package_version` method of a `DependencyProvider`. -- Implement `FromStr` for `SemanticVersion`. -- Add the `VersionParseError` type for parsing of semantic versions. - -#### Changed - -- The `Solver` trait was replaced by a `DependencyProvider` trait - which now must implement a `choose_package_version` method - instead of `list_available_versions`. - So it now has the ability to choose a package in addition to a version. - The `DependencyProvider` also has a new optional method `should_cancel` - that may be used to stop the solver if needed. -- The `choose_package_version` and `get_dependencies` methods of the - `DependencyProvider` trait now take an immutable reference to `self`. - Interior mutability can be used by implementor if mutability is needed. -- The `Solver.run` method was thus replaced by a free function `solver::resolve` - taking a dependency provider as first argument. -- The `OfflineSolver` is thus replaced by an `OfflineDependencyProvider`. -- `SemanticVersion` now takes `u32` instead of `usize` for its 3 parts. -- `NumberVersion` now uses `u32` instead of `usize`. - -#### Removed - -- `ErrorRetrievingVersions` variant of `error::PubGrubError`. - -### Changes in the internal parts of the API - -#### Added - -- `benches/large_case.rs` enables benchmarking of serialized registries of packages. -- `examples/caching_dependency_provider.rs` an example dependency provider caching dependencies. -- `PackageTerm = (P, Term)` new type alias for readability. -- `Memory.term_intersection_for_package(&mut self, package: &P) -> Option<&Term>` -- New types were introduces for conflict resolution in `internal::partial_solution` - to clarify the intent and return values of some functions. - Those types are `DatedAssignment` and `SatisfierAndPreviousHistory`. -- `PartialSolution.term_intersection_for_package` calling the same function - from its `memory`. -- New property tests for ranges: `negate_contains_opposite`, `intesection_contains_both` - and `union_contains_either`. -- A large synthetic test case was added in `test-examples/`. -- A new test example `double_choices` was added - for the detection of a bug (fixed) in the implementation. -- Property testing of big synthetic datasets was added in `tests/proptest.rs`. -- Comparison of PubGrub solver and a SAT solver - was added with `tests/sat_dependency_provider.rs`. -- Other regression and unit tests were added to `tests/tests.rs`. - -#### Changed - -- CI workflow was improved (`./github/workflows/`), including a check for - [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) and - [Clippy](https://github.com/rust-lang/rust-clippy) for source code linting. -- Using SPDX license identifiers instead of MPL-2.0 classic file headers. -- `State.incompatibilities` is now wrapped inside a `Rc`. -- `DecisionLevel(u32)` is used in place of `usize` for partial solution decision levels. -- `State.conflict_resolution` now also returns the almost satisfied package - to avoid an unnecessary call to `self.partial_solution.relation(...)` after conflict resolution. -- `Kind::NoVersion` renamed to `Kind::NoVersions` and all other usage of `noversion` - has been changed to `no_versions`. -- Variants of the `incompatibility::Relation` enum have changed. -- Incompatibility now uses a deterministic hasher to store packages in its hash map. -- `incompatibility.relation(...)` now takes a function as argument to avoid computations - of unnecessary terms intersections. -- `Memory` now uses a deterministic hasher instead of the default one. -- `memory::PackageAssignments` is now an enum instead of a struct. -- Derivations in a `PackageAssignments` keep a precomputed intersection of derivation terms. -- `potential_packages` method now returns a `Range` - instead of a `Term` for the versions constraint of each package. -- `PartialSolution.relation` now takes `&mut self` instead of `&self` - to be able to store computation of terms intersection. -- `Term.accept_version` was renamed `Term.contains`. -- The `satisfied_by` and `contradicted_by` methods of a `Term` - now directly takes a reference to the intersection of other terms. - Same for `relation_with`. - -#### Removed - -- `term` field of an `Assignment::Derivation` variant. -- `Memory.all_terms` method was removed. -- `Memory.remove_decision` method was removed in favor of a check before using `Memory.add_decision`. -- `PartialSolution` methods `pick_package` and `pick_version` have been removed - since control was given back to the dependency provider to choose a package version. -- `PartialSolution` methods `remove_last_decision` and `satisfies_any_of` were removed - in favor of a preventive check before calling `add_decision`. -- `Term.is_negative`. - -#### Fixed - -- Prior cause computation (`incompatibility::prior_cause`) now uses the intersection of package terms - instead of their union, which was an implementation error. - -## [0.1.0] - 2020-10-01 - -### Added - -- `README.md` as the home page of this repository. -- `LICENSE`, code is provided under the MPL 2.0 license. -- `Cargo.toml` configuration of this Rust project. -- `src/` containing all the source code for this first implementation of PubGrub in Rust. -- `tests/` containing test end-to-end examples. -- `examples/` other examples, not in the form of tests. -- `.gitignore` configured for a Rust project. -- `.github/workflows/` CI to automatically build, test and document on push and pull requests. - -[0.2.1]: https://github.com/pubgrub-rs/pubgrub/releases/tag/v0.2.1 -[0.2.0]: https://github.com/pubgrub-rs/pubgrub/releases/tag/v0.2.0 -[0.1.0]: https://github.com/pubgrub-rs/pubgrub/releases/tag/v0.1.0 - -[unreleased-diff]: https://github.com/pubgrub-rs/pubgrub/compare/release...dev -[0.2.0-diff]: https://github.com/pubgrub-rs/pubgrub/compare/v0.2.0...v0.2.1 -[0.1.0-diff]: https://github.com/pubgrub-rs/pubgrub/compare/v0.1.0...v0.2.0 diff --git a/vendor/pubgrub/Cargo.toml b/vendor/pubgrub/Cargo.toml deleted file mode 100644 index a4c94e696..000000000 --- a/vendor/pubgrub/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -# SPDX-License-Identifier: MPL-2.0 - -[package] -name = "pubgrub" -version = "0.2.1" -authors = [ - "Matthieu Pizenberg ", - "Alex Tokarev ", - "Jacob Finkelman ", -] -edition = "2021" -description = "PubGrub version solving algorithm" -readme = "README.md" -repository = "https://github.com/pubgrub-rs/pubgrub" -license = "MPL-2.0" -keywords = ["dependency", "pubgrub", "semver", "solver", "version"] -categories = ["algorithms"] -include = ["Cargo.toml", "LICENSE", "README.md", "src/**", "tests/**", "examples/**", "benches/**"] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -indexmap = "2.0.2" -priority-queue = "1.1.1" -thiserror = "1.0" -rustc-hash = "1.1.0" -serde = { version = "1.0", features = ["derive"], optional = true } -log = "0.4.14" # for debug logs in tests - -[dev-dependencies] -proptest = "0.10.1" -ron = "0.6" -varisat = "0.2.2" -criterion = "0.3" -env_logger = "0.9.0" - -[[bench]] -name = "large_case" -harness = false -required-features = ["serde"] diff --git a/vendor/pubgrub/LICENSE b/vendor/pubgrub/LICENSE deleted file mode 100644 index a612ad981..000000000 --- a/vendor/pubgrub/LICENSE +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/vendor/pubgrub/README.md b/vendor/pubgrub/README.md deleted file mode 100644 index 2bddc3f41..000000000 --- a/vendor/pubgrub/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# PubGrub version solving algorithm - -![license](https://img.shields.io/crates/l/pubgrub.svg) -[![crates.io](https://img.shields.io/crates/v/pubgrub.svg?logo=rust)][crates] -[![docs.rs](https://img.shields.io/badge/docs.rs-pubgrub-yellow)][docs] -[![guide](https://img.shields.io/badge/guide-pubgrub-pink?logo=read-the-docs)][guide] - -Version solving consists in efficiently finding a set of packages and versions -that satisfy all the constraints of a given project dependencies. -In addition, when that is not possible, -PubGrub tries to provide a very human-readable and clear -explanation as to why that failed. -The [introductory blog post about PubGrub][medium-pubgrub] presents -one such example of failure explanation: - -```txt -Because dropdown >=2.0.0 depends on icons >=2.0.0 and - root depends on icons <2.0.0, dropdown >=2.0.0 is forbidden. - -And because menu >=1.1.0 depends on dropdown >=2.0.0, - menu >=1.1.0 is forbidden. - -And because menu <1.1.0 depends on dropdown >=1.0.0 <2.0.0 - which depends on intl <4.0.0, every version of menu - requires intl <4.0.0. - -So, because root depends on both menu >=1.0.0 and intl >=5.0.0, - version solving failed. -``` - -This pubgrub crate provides a Rust implementation of PubGrub. -It is generic and works for any type of dependency system -as long as packages (P) and versions (V) implement -the provided `Package` and `Version` traits. - - -## Using the pubgrub crate - -A [guide][guide] with both high-level explanations and -in-depth algorithm details is available online. -The [API documentation is available on docs.rs][docs]. -A version of the [API docs for the unreleased functionality][docs-dev] from `dev` branch is also -accessible for convenience. - - -## Contributing - -Discussion and development happens here on GitHub and on our -[Zulip stream](https://rust-lang.zulipchat.com/#narrow/stream/260232-t-cargo.2FPubGrub). -Please join in! - -Remember to always be considerate of others, -who may have different native languages, cultures and experiences. -We want everyone to feel welcomed, -let us know with a private message on Zulip if you don't feel that way. - - -## PubGrub - -PubGrub is a version solving algorithm, -written in 2018 by Natalie Weizenbaum -for the Dart package manager. -It is supposed to be very fast and to explain errors -more clearly than the alternatives. -An introductory blog post was -[published on Medium][medium-pubgrub] by its author. - -The detailed explanation of the algorithm is -[provided on GitHub][github-pubgrub], -and complemented by the ["Internals" section of our guide][guide-internals]. -The foundation of the algorithm is based on ASP (Answer Set Programming), -and a book called -"[Answer Set Solving in Practice][potassco-book]" -by Martin Gebser, Roland Kaminski, Benjamin Kaufmann and Torsten Schaub. - -[crates]: https://crates.io/crates/pubgrub -[guide]: https://pubgrub-rs-guide.netlify.app/ -[guide-internals]: https://pubgrub-rs-guide.netlify.app/internals/intro.html -[docs]: https://docs.rs/pubgrub -[docs-dev]: https://pubgrub-rs.github.io/pubgrub/pubgrub/ -[medium-pubgrub]: https://medium.com/@nex3/pubgrub-2fb6470504f -[github-pubgrub]: https://github.com/dart-lang/pub/blob/master/doc/solver.md -[potassco-book]: https://potassco.org/book/ diff --git a/vendor/pubgrub/benches/large_case.rs b/vendor/pubgrub/benches/large_case.rs deleted file mode 100644 index 8efdaa9ef..000000000 --- a/vendor/pubgrub/benches/large_case.rs +++ /dev/null @@ -1,54 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 -use std::time::Duration; - -extern crate criterion; -use self::criterion::*; - -use pubgrub::package::Package; -use pubgrub::range::Range; -use pubgrub::solver::{resolve, OfflineDependencyProvider}; -use pubgrub::version::{NumberVersion, SemanticVersion}; -use pubgrub::version_set::VersionSet; -use serde::de::Deserialize; - -fn bench<'a, P: Package + Deserialize<'a>, VS: VersionSet + Deserialize<'a>>( - b: &mut Bencher, - case: &'a str, -) where - ::V: Deserialize<'a>, -{ - let dependency_provider: OfflineDependencyProvider = ron::de::from_str(&case).unwrap(); - - b.iter(|| { - for p in dependency_provider.packages() { - for n in dependency_provider.versions(p).unwrap() { - let _ = resolve(&dependency_provider, p.clone(), n.clone()); - } - } - }); -} - -fn bench_nested(c: &mut Criterion) { - let mut group = c.benchmark_group("large_cases"); - group.measurement_time(Duration::from_secs(20)); - - for case in std::fs::read_dir("test-examples").unwrap() { - let case = case.unwrap().path(); - let name = case.file_name().unwrap().to_string_lossy(); - let data = std::fs::read_to_string(&case).unwrap(); - if name.ends_with("u16_NumberVersion.ron") { - group.bench_function(name, |b| { - bench::>(b, &data); - }); - } else if name.ends_with("str_SemanticVersion.ron") { - group.bench_function(name, |b| { - bench::<&str, Range>(b, &data); - }); - } - } - - group.finish(); -} - -criterion_group!(benches, bench_nested); -criterion_main!(benches); diff --git a/vendor/pubgrub/examples/branching_error_reporting.rs b/vendor/pubgrub/examples/branching_error_reporting.rs deleted file mode 100644 index d4dfb719c..000000000 --- a/vendor/pubgrub/examples/branching_error_reporting.rs +++ /dev/null @@ -1,67 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use pubgrub::error::PubGrubError; -use pubgrub::range::Range; -use pubgrub::report::{DefaultStringReporter, Reporter}; -use pubgrub::solver::{resolve, OfflineDependencyProvider}; -use pubgrub::version::SemanticVersion; - -type SemVS = Range; - -// https://github.com/dart-lang/pub/blob/master/doc/solver.md#branching-error-reporting -fn main() { - let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new(); - #[rustfmt::skip] - // root 1.0.0 depends on foo ^1.0.0 - dependency_provider.add_dependencies( - "root", (1, 0, 0), - [("foo", Range::from_range_bounds((1, 0, 0)..(2, 0, 0)))], - ); - #[rustfmt::skip] - // foo 1.0.0 depends on a ^1.0.0 and b ^1.0.0 - dependency_provider.add_dependencies( - "foo", (1, 0, 0), - [ - ("a", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))), - ("b", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))), - ], - ); - #[rustfmt::skip] - // foo 1.1.0 depends on x ^1.0.0 and y ^1.0.0 - dependency_provider.add_dependencies( - "foo", (1, 1, 0), - [ - ("x", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))), - ("y", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))), - ], - ); - #[rustfmt::skip] - // a 1.0.0 depends on b ^2.0.0 - dependency_provider.add_dependencies( - "a", (1, 0, 0), - [("b", Range::from_range_bounds((2, 0, 0)..(3, 0, 0)))], - ); - // b 1.0.0 and 2.0.0 have no dependencies. - dependency_provider.add_dependencies("b", (1, 0, 0), []); - dependency_provider.add_dependencies("b", (2, 0, 0), []); - #[rustfmt::skip] - // x 1.0.0 depends on y ^2.0.0. - dependency_provider.add_dependencies( - "x", (1, 0, 0), - [("y", Range::from_range_bounds((2, 0, 0)..(3, 0, 0)))], - ); - // y 1.0.0 and 2.0.0 have no dependencies. - dependency_provider.add_dependencies("y", (1, 0, 0), []); - dependency_provider.add_dependencies("y", (2, 0, 0), []); - - // Run the algorithm. - match resolve(&dependency_provider, "root", (1, 0, 0)) { - Ok(sol) => println!("{:?}", sol), - Err(PubGrubError::NoSolution(mut derivation_tree)) => { - derivation_tree.collapse_no_versions(); - eprintln!("{}", DefaultStringReporter::report(&derivation_tree)); - std::process::exit(1); - } - Err(err) => panic!("{:?}", err), - }; -} diff --git a/vendor/pubgrub/examples/caching_dependency_provider.rs b/vendor/pubgrub/examples/caching_dependency_provider.rs deleted file mode 100644 index 6ef8e893f..000000000 --- a/vendor/pubgrub/examples/caching_dependency_provider.rs +++ /dev/null @@ -1,90 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use std::cell::RefCell; -use std::error::Error; - -use pubgrub::package::Package; -use pubgrub::range::Range; -use pubgrub::solver::{resolve, Dependencies, DependencyProvider, OfflineDependencyProvider}; -use pubgrub::version::NumberVersion; -use pubgrub::version_set::VersionSet; - -type NumVS = Range; - -// An example implementing caching dependency provider that will -// store queried dependencies in memory and check them before querying more from remote. -struct CachingDependencyProvider> { - remote_dependencies: DP, - cached_dependencies: RefCell>, -} - -impl> - CachingDependencyProvider -{ - pub fn new(remote_dependencies_provider: DP) -> Self { - CachingDependencyProvider { - remote_dependencies: remote_dependencies_provider, - cached_dependencies: RefCell::new(OfflineDependencyProvider::new()), - } - } -} - -impl> DependencyProvider - for CachingDependencyProvider -{ - // Caches dependencies if they were already queried - fn get_dependencies( - &self, - package: &P, - version: &VS::V, - ) -> Result, Box> { - let mut cache = self.cached_dependencies.borrow_mut(); - match cache.get_dependencies(package, version) { - Ok(Dependencies::Unknown) => { - let dependencies = self.remote_dependencies.get_dependencies(package, version); - match dependencies { - Ok(Dependencies::Known(dependencies)) => { - cache.add_dependencies( - package.clone(), - version.clone(), - dependencies.clone(), - ); - Ok(Dependencies::Known(dependencies)) - } - Ok(Dependencies::Unknown) => Ok(Dependencies::Unknown), - error @ Err(_) => error, - } - } - dependencies @ Ok(_) => dependencies, - error @ Err(_) => error, - } - } - - fn choose_version( - &self, - package: &P, - range: &VS, - ) -> Result, Box> { - self.remote_dependencies.choose_version(package, range) - } - - type Priority = DP::Priority; - - fn prioritize(&self, package: &P, range: &VS) -> Self::Priority { - self.remote_dependencies.prioritize(package, range) - } -} - -fn main() { - // Simulating remote provider locally. - let mut remote_dependencies_provider = OfflineDependencyProvider::<&str, NumVS>::new(); - - // Add dependencies as needed. Here only root package is added. - remote_dependencies_provider.add_dependencies("root", 1, Vec::new()); - - let caching_dependencies_provider = - CachingDependencyProvider::new(remote_dependencies_provider); - - let solution = resolve(&caching_dependencies_provider, "root", 1); - println!("Solution: {:?}", solution); -} diff --git a/vendor/pubgrub/examples/doc_interface.rs b/vendor/pubgrub/examples/doc_interface.rs deleted file mode 100644 index ca6bcb930..000000000 --- a/vendor/pubgrub/examples/doc_interface.rs +++ /dev/null @@ -1,26 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use pubgrub::range::Range; -use pubgrub::solver::{resolve, OfflineDependencyProvider}; -use pubgrub::version::NumberVersion; - -type NumVS = Range; - -// `root` depends on `menu` and `icons` -// `menu` depends on `dropdown` -// `dropdown` depends on `icons` -// `icons` has no dependency -#[rustfmt::skip] -fn main() { - let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new(); - dependency_provider.add_dependencies( - "root", 1, [("menu", Range::full()), ("icons", Range::full())], - ); - dependency_provider.add_dependencies("menu", 1, [("dropdown", Range::full())]); - dependency_provider.add_dependencies("dropdown", 1, [("icons", Range::full())]); - dependency_provider.add_dependencies("icons", 1, []); - - // Run the algorithm. - let solution = resolve(&dependency_provider, "root", 1); - println!("Solution: {:?}", solution); -} diff --git a/vendor/pubgrub/examples/doc_interface_error.rs b/vendor/pubgrub/examples/doc_interface_error.rs deleted file mode 100644 index a78a3eb30..000000000 --- a/vendor/pubgrub/examples/doc_interface_error.rs +++ /dev/null @@ -1,83 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use pubgrub::error::PubGrubError; -use pubgrub::range::Range; -use pubgrub::report::{DefaultStringReporter, Reporter}; -use pubgrub::solver::{resolve, OfflineDependencyProvider}; -use pubgrub::version::SemanticVersion; - -type SemVS = Range; - -// `root` depends on `menu`, `icons 1.0.0` and `intl 5.0.0` -// `menu 1.0.0` depends on `dropdown < 2.0.0` -// `menu >= 1.1.0` depends on `dropdown >= 2.0.0` -// `dropdown 1.8.0` depends on `intl 3.0.0` -// `dropdown >= 2.0.0` depends on `icons 2.0.0` -// `icons` has no dependency -// `intl` has no dependency -#[rustfmt::skip] -fn main() { - let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new(); - // Direct dependencies: menu and icons. - dependency_provider.add_dependencies("root", (1, 0, 0), [ - ("menu", Range::full()), - ("icons", Range::singleton((1, 0, 0))), - ("intl", Range::singleton((5, 0, 0))), - ]); - - // Dependencies of the menu lib. - dependency_provider.add_dependencies("menu", (1, 0, 0), [ - ("dropdown", Range::from_range_bounds(..(2, 0, 0))), - ]); - dependency_provider.add_dependencies("menu", (1, 1, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - dependency_provider.add_dependencies("menu", (1, 2, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - dependency_provider.add_dependencies("menu", (1, 3, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - dependency_provider.add_dependencies("menu", (1, 4, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - dependency_provider.add_dependencies("menu", (1, 5, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - - // Dependencies of the dropdown lib. - dependency_provider.add_dependencies("dropdown", (1, 8, 0), [ - ("intl", Range::singleton((3, 0, 0))), - ]); - dependency_provider.add_dependencies("dropdown", (2, 0, 0), [ - ("icons", Range::singleton((2, 0, 0))), - ]); - dependency_provider.add_dependencies("dropdown", (2, 1, 0), [ - ("icons", Range::singleton((2, 0, 0))), - ]); - dependency_provider.add_dependencies("dropdown", (2, 2, 0), [ - ("icons", Range::singleton((2, 0, 0))), - ]); - dependency_provider.add_dependencies("dropdown", (2, 3, 0), [ - ("icons", Range::singleton((2, 0, 0))), - ]); - - // Icons have no dependencies. - dependency_provider.add_dependencies("icons", (1, 0, 0), []); - dependency_provider.add_dependencies("icons", (2, 0, 0), []); - - // Intl have no dependencies. - dependency_provider.add_dependencies("intl", (3, 0, 0), []); - dependency_provider.add_dependencies("intl", (4, 0, 0), []); - dependency_provider.add_dependencies("intl", (5, 0, 0), []); - - // Run the algorithm. - match resolve(&dependency_provider, "root", (1, 0, 0)) { - Ok(sol) => println!("{:?}", sol), - Err(PubGrubError::NoSolution(mut derivation_tree)) => { - derivation_tree.collapse_no_versions(); - eprintln!("{}", DefaultStringReporter::report(&derivation_tree)); - } - Err(err) => panic!("{:?}", err), - }; -} diff --git a/vendor/pubgrub/examples/doc_interface_semantic.rs b/vendor/pubgrub/examples/doc_interface_semantic.rs deleted file mode 100644 index 17ff3c094..000000000 --- a/vendor/pubgrub/examples/doc_interface_semantic.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use pubgrub::error::PubGrubError; -use pubgrub::range::Range; -use pubgrub::report::{DefaultStringReporter, Reporter}; -use pubgrub::solver::{resolve, OfflineDependencyProvider}; -use pubgrub::version::SemanticVersion; - -type SemVS = Range; - -// `root` depends on `menu` and `icons 1.0.0` -// `menu 1.0.0` depends on `dropdown < 2.0.0` -// `menu >= 1.1.0` depends on `dropdown >= 2.0.0` -// `dropdown 1.8.0` has no dependency -// `dropdown >= 2.0.0` depends on `icons 2.0.0` -// `icons` has no dependency -#[rustfmt::skip] -fn main() { - let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new(); - // Direct dependencies: menu and icons. - dependency_provider.add_dependencies("root", (1, 0, 0), [ - ("menu", Range::full()), - ("icons", Range::singleton((1, 0, 0))), - ]); - - // Dependencies of the menu lib. - dependency_provider.add_dependencies("menu", (1, 0, 0), [ - ("dropdown", Range::from_range_bounds(..(2, 0, 0))), - ]); - dependency_provider.add_dependencies("menu", (1, 1, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - dependency_provider.add_dependencies("menu", (1, 2, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - dependency_provider.add_dependencies("menu", (1, 3, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - dependency_provider.add_dependencies("menu", (1, 4, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - dependency_provider.add_dependencies("menu", (1, 5, 0), [ - ("dropdown", Range::from_range_bounds((2, 0, 0)..)), - ]); - - // Dependencies of the dropdown lib. - dependency_provider.add_dependencies("dropdown", (1, 8, 0), []); - dependency_provider.add_dependencies("dropdown", (2, 0, 0), [ - ("icons", Range::singleton((2, 0, 0))), - ]); - dependency_provider.add_dependencies("dropdown", (2, 1, 0), [ - ("icons", Range::singleton((2, 0, 0))), - ]); - dependency_provider.add_dependencies("dropdown", (2, 2, 0), [ - ("icons", Range::singleton((2, 0, 0))), - ]); - dependency_provider.add_dependencies("dropdown", (2, 3, 0), [ - ("icons", Range::singleton((2, 0, 0))), - ]); - - // Icons has no dependency. - dependency_provider.add_dependencies("icons", (1, 0, 0), []); - dependency_provider.add_dependencies("icons", (2, 0, 0), []); - - // Run the algorithm. - match resolve(&dependency_provider, "root", (1, 0, 0)) { - Ok(sol) => println!("{:?}", sol), - Err(PubGrubError::NoSolution(mut derivation_tree)) => { - derivation_tree.collapse_no_versions(); - eprintln!("{}", DefaultStringReporter::report(&derivation_tree)); - } - Err(err) => panic!("{:?}", err), - }; -} diff --git a/vendor/pubgrub/examples/linear_error_reporting.rs b/vendor/pubgrub/examples/linear_error_reporting.rs deleted file mode 100644 index 8624fe2aa..000000000 --- a/vendor/pubgrub/examples/linear_error_reporting.rs +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use pubgrub::error::PubGrubError; -use pubgrub::range::Range; -use pubgrub::report::{DefaultStringReporter, Reporter}; -use pubgrub::solver::{resolve, OfflineDependencyProvider}; -use pubgrub::version::SemanticVersion; - -type SemVS = Range; - -// https://github.com/dart-lang/pub/blob/master/doc/solver.md#linear-error-reporting -fn main() { - let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new(); - #[rustfmt::skip] - // root 1.0.0 depends on foo ^1.0.0 and baz ^1.0.0 - dependency_provider.add_dependencies( - "root", (1, 0, 0), - [ - ("foo", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))), - ("baz", Range::from_range_bounds((1, 0, 0)..(2, 0, 0))), - ], - ); - #[rustfmt::skip] - // foo 1.0.0 depends on bar ^2.0.0 - dependency_provider.add_dependencies( - "foo", (1, 0, 0), - [("bar", Range::from_range_bounds((2, 0, 0)..(3, 0, 0)))], - ); - #[rustfmt::skip] - // bar 2.0.0 depends on baz ^3.0.0 - dependency_provider.add_dependencies( - "bar", (2, 0, 0), - [("baz", Range::from_range_bounds((3, 0, 0)..(4, 0, 0)))], - ); - // baz 1.0.0 and 3.0.0 have no dependencies - dependency_provider.add_dependencies("baz", (1, 0, 0), []); - dependency_provider.add_dependencies("baz", (3, 0, 0), []); - - // Run the algorithm. - match resolve(&dependency_provider, "root", (1, 0, 0)) { - Ok(sol) => println!("{:?}", sol), - Err(PubGrubError::NoSolution(mut derivation_tree)) => { - derivation_tree.collapse_no_versions(); - eprintln!("{}", DefaultStringReporter::report(&derivation_tree)); - std::process::exit(1); - } - Err(err) => panic!("{:?}", err), - }; -} diff --git a/vendor/pubgrub/release.md b/vendor/pubgrub/release.md deleted file mode 100644 index fdbd1a1fe..000000000 --- a/vendor/pubgrub/release.md +++ /dev/null @@ -1,28 +0,0 @@ -# Creation of a new release - -This is taking the 0.2.1 release as an example. - -## GitHub stuff - -- Checkout the prep-v0.2.1 branch -- Update the release date in the changelog and push to the PR. -- Squash merge the PR to the dev branch -- Check that the merged PRĀ is passing the tests on the dev branch -- Pull the updated dev locally -- Switch to the release branch -- Merge locally dev into release in fast-forward mode, we want to keep the history of commits and the merge point. -- `git tag -a v0.2.1 -m "v0.2.1: mostly perf improvements"` -- (Optional) cryptographically sign the tag -- On GitHub, edit the branch protection setting for release: uncheck include admin, and save -- Push release to github: git push --follow-tags -- Reset the release branch protection to include admins -- On GitHub, create a release from that tag. - -## Crates.io stuff - -- `cargo publish --dry-run` -- `cargo publish` - -## Community stuff - -Talk about the awesome new features of the new release online. diff --git a/vendor/pubgrub/src/error.rs b/vendor/pubgrub/src/error.rs deleted file mode 100644 index 15a410e33..000000000 --- a/vendor/pubgrub/src/error.rs +++ /dev/null @@ -1,61 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Handling pubgrub errors. - -use thiserror::Error; - -use crate::package::Package; -use crate::report::DerivationTree; -use crate::version_set::VersionSet; - -/// Errors that may occur while solving dependencies. -#[derive(Error, Debug)] -pub enum PubGrubError { - /// There is no solution for this set of dependencies. - #[error("No solution")] - NoSolution(DerivationTree), - - /// Error arising when the implementer of - /// [DependencyProvider](crate::solver::DependencyProvider) - /// returned an error in the method - /// [get_dependencies](crate::solver::DependencyProvider::get_dependencies). - #[error("Retrieving dependencies of {package} {version} failed")] - ErrorRetrievingDependencies { - /// Package whose dependencies we want. - package: P, - /// Version of the package for which we want the dependencies. - version: VS::V, - /// Error raised by the implementer of - /// [DependencyProvider](crate::solver::DependencyProvider). - source: Box, - }, - - /// Error arising when the implementer of - /// [DependencyProvider](crate::solver::DependencyProvider) - /// returned a dependency on the requested package. - /// This technically means that the package directly depends on itself, - /// and is clearly some kind of mistake. - #[error("{package} {version} depends on itself")] - SelfDependency { - /// Package whose dependencies we want. - package: P, - /// Version of the package for which we want the dependencies. - version: VS::V, - }, - - /// Error arising when the implementer of - /// [DependencyProvider](crate::solver::DependencyProvider) - /// returned an error in the method - /// [choose_version](crate::solver::DependencyProvider::choose_version). - #[error("Decision making failed")] - ErrorChoosingPackageVersion(Box), - - /// Error arising when the implementer of [DependencyProvider](crate::solver::DependencyProvider) - /// returned an error in the method [should_cancel](crate::solver::DependencyProvider::should_cancel). - #[error("We should cancel")] - ErrorInShouldCancel(Box), - - /// Something unexpected happened. - #[error("{0}")] - Failure(String), -} diff --git a/vendor/pubgrub/src/internal/arena.rs b/vendor/pubgrub/src/internal/arena.rs deleted file mode 100644 index 7b4fc1601..000000000 --- a/vendor/pubgrub/src/internal/arena.rs +++ /dev/null @@ -1,122 +0,0 @@ -use std::{ - fmt, - hash::{Hash, Hasher}, - marker::PhantomData, - ops::{Index, Range}, -}; - -/// The index of a value allocated in an arena that holds `T`s. -/// -/// The Clone, Copy and other traits are defined manually because -/// deriving them adds some additional constraints on the `T` generic type -/// that we actually don't need since it is phantom. -/// -/// -pub struct Id { - raw: u32, - _ty: PhantomData T>, -} - -impl Clone for Id { - fn clone(&self) -> Self { - *self - } -} - -impl Copy for Id {} - -impl PartialEq for Id { - fn eq(&self, other: &Id) -> bool { - self.raw == other.raw - } -} - -impl Eq for Id {} - -impl Hash for Id { - fn hash(&self, state: &mut H) { - self.raw.hash(state) - } -} - -impl fmt::Debug for Id { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let mut type_name = std::any::type_name::(); - if let Some(id) = type_name.rfind(':') { - type_name = &type_name[id + 1..] - } - write!(f, "Id::<{}>({})", type_name, self.raw) - } -} - -impl Id { - pub fn into_raw(self) -> usize { - self.raw as usize - } - fn from(n: u32) -> Self { - Self { - raw: n, - _ty: PhantomData, - } - } - pub fn range_to_iter(range: Range) -> impl Iterator { - let start = range.start.raw; - let end = range.end.raw; - (start..end).map(Self::from) - } -} - -/// Yet another index-based arena. -/// -/// An arena is a kind of simple grow-only allocator, backed by a `Vec` -/// where all items have the same lifetime, making it easier -/// to have references between those items. -/// They are all dropped at once when the arena is dropped. -#[derive(Clone, PartialEq, Eq)] -pub struct Arena { - data: Vec, -} - -impl fmt::Debug for Arena { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - fmt.debug_struct("Arena") - .field("len", &self.data.len()) - .field("data", &self.data) - .finish() - } -} - -impl Arena { - pub fn new() -> Arena { - Arena { data: Vec::new() } - } - - pub fn alloc(&mut self, value: T) -> Id { - let raw = self.data.len(); - self.data.push(value); - Id::from(raw as u32) - } - - pub fn alloc_iter>(&mut self, values: I) -> Range> { - let start = Id::from(self.data.len() as u32); - values.for_each(|v| { - self.alloc(v); - }); - let end = Id::from(self.data.len() as u32); - Range { start, end } - } -} - -impl Index> for Arena { - type Output = T; - fn index(&self, id: Id) -> &T { - &self.data[id.raw as usize] - } -} - -impl Index>> for Arena { - type Output = [T]; - fn index(&self, id: Range>) -> &[T] { - &self.data[(id.start.raw as usize)..(id.end.raw as usize)] - } -} diff --git a/vendor/pubgrub/src/internal/core.rs b/vendor/pubgrub/src/internal/core.rs deleted file mode 100644 index a4a23b341..000000000 --- a/vendor/pubgrub/src/internal/core.rs +++ /dev/null @@ -1,273 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Core model and functions -//! to write a functional PubGrub algorithm. - -use std::collections::HashSet as Set; - -use crate::error::PubGrubError; -use crate::internal::arena::Arena; -use crate::internal::incompatibility::{IncompId, Incompatibility, Relation}; -use crate::internal::partial_solution::SatisfierSearch::{ - DifferentDecisionLevels, SameDecisionLevels, -}; -use crate::internal::partial_solution::{DecisionLevel, PartialSolution}; -use crate::internal::small_vec::SmallVec; -use crate::package::Package; -use crate::report::DerivationTree; -use crate::type_aliases::{DependencyConstraints, Map}; -use crate::version_set::VersionSet; - -/// Current state of the PubGrub algorithm. -#[derive(Clone)] -pub struct State { - root_package: P, - root_version: VS::V, - - pub incompatibilities: Map>>, - - /// Store the ids of incompatibilities that are already contradicted - /// and will stay that way until the next conflict and backtrack is operated. - contradicted_incompatibilities: rustc_hash::FxHashSet>, - - /// Partial solution. - /// TODO: remove pub. - pub partial_solution: PartialSolution, - - /// The store is the reference storage for all incompatibilities. - pub incompatibility_store: Arena>, - - /// This is a stack of work to be done in `unit_propagation`. - /// It can definitely be a local variable to that method, but - /// this way we can reuse the same allocation for better performance. - unit_propagation_buffer: SmallVec

, -} - -impl State { - /// Initialization of PubGrub state. - pub fn init(root_package: P, root_version: VS::V) -> Self { - let mut incompatibility_store = Arena::new(); - let not_root_id = incompatibility_store.alloc(Incompatibility::not_root( - root_package.clone(), - root_version.clone(), - )); - let mut incompatibilities = Map::default(); - incompatibilities.insert(root_package.clone(), vec![not_root_id]); - Self { - root_package, - root_version, - incompatibilities, - contradicted_incompatibilities: rustc_hash::FxHashSet::default(), - partial_solution: PartialSolution::empty(), - incompatibility_store, - unit_propagation_buffer: SmallVec::Empty, - } - } - - /// Add an incompatibility to the state. - pub fn add_incompatibility(&mut self, incompat: Incompatibility) { - let id = self.incompatibility_store.alloc(incompat); - self.merge_incompatibility(id); - } - - /// Add an incompatibility to the state. - pub fn add_incompatibility_from_dependencies( - &mut self, - package: P, - version: VS::V, - deps: &DependencyConstraints, - ) -> std::ops::Range> { - // Create incompatibilities and allocate them in the store. - let new_incompats_id_range = self - .incompatibility_store - .alloc_iter(deps.iter().map(|dep| { - Incompatibility::from_dependency(package.clone(), version.clone(), dep) - })); - // Merge the newly created incompatibilities with the older ones. - for id in IncompId::range_to_iter(new_incompats_id_range.clone()) { - self.merge_incompatibility(id); - } - new_incompats_id_range - } - - /// Unit propagation is the core mechanism of the solving algorithm. - /// CF - pub fn unit_propagation(&mut self, package: P) -> Result<(), PubGrubError> { - self.unit_propagation_buffer.clear(); - self.unit_propagation_buffer.push(package); - while let Some(current_package) = self.unit_propagation_buffer.pop() { - // Iterate over incompatibilities in reverse order - // to evaluate first the newest incompatibilities. - let mut conflict_id = None; - // We only care about incompatibilities if it contains the current package. - for &incompat_id in self.incompatibilities[¤t_package].iter().rev() { - if self.contradicted_incompatibilities.contains(&incompat_id) { - continue; - } - let current_incompat = &self.incompatibility_store[incompat_id]; - match self.partial_solution.relation(current_incompat) { - // If the partial solution satisfies the incompatibility - // we must perform conflict resolution. - Relation::Satisfied => { - log::info!( - "Start conflict resolution because incompat satisfied:\n {}", - current_incompat - ); - conflict_id = Some(incompat_id); - break; - } - Relation::AlmostSatisfied(package_almost) => { - self.unit_propagation_buffer.push(package_almost.clone()); - // Add (not term) to the partial solution with incompat as cause. - self.partial_solution.add_derivation( - package_almost, - incompat_id, - &self.incompatibility_store, - ); - // With the partial solution updated, the incompatibility is now contradicted. - self.contradicted_incompatibilities.insert(incompat_id); - } - Relation::Contradicted(_) => { - self.contradicted_incompatibilities.insert(incompat_id); - } - _ => {} - } - } - if let Some(incompat_id) = conflict_id { - let (package_almost, root_cause) = self.conflict_resolution(incompat_id)?; - self.unit_propagation_buffer.clear(); - self.unit_propagation_buffer.push(package_almost.clone()); - // Add to the partial solution with incompat as cause. - self.partial_solution.add_derivation( - package_almost, - root_cause, - &self.incompatibility_store, - ); - // After conflict resolution and the partial solution update, - // the root cause incompatibility is now contradicted. - self.contradicted_incompatibilities.insert(root_cause); - } - } - // If there are no more changed packages, unit propagation is done. - Ok(()) - } - - /// Return the root cause and the backtracked model. - /// CF - fn conflict_resolution( - &mut self, - incompatibility: IncompId, - ) -> Result<(P, IncompId), PubGrubError> { - let mut current_incompat_id = incompatibility; - let mut current_incompat_changed = false; - loop { - if self.incompatibility_store[current_incompat_id] - .is_terminal(&self.root_package, &self.root_version) - { - return Err(PubGrubError::NoSolution( - self.build_derivation_tree(current_incompat_id), - )); - } else { - let (package, satisfier_search_result) = self.partial_solution.satisfier_search( - &self.incompatibility_store[current_incompat_id], - &self.incompatibility_store, - ); - match satisfier_search_result { - DifferentDecisionLevels { - previous_satisfier_level, - } => { - self.backtrack( - current_incompat_id, - current_incompat_changed, - previous_satisfier_level, - ); - log::info!("backtrack to {:?}", previous_satisfier_level); - return Ok((package, current_incompat_id)); - } - SameDecisionLevels { satisfier_cause } => { - let prior_cause = Incompatibility::prior_cause( - current_incompat_id, - satisfier_cause, - &package, - &self.incompatibility_store, - ); - log::info!("prior cause: {}", prior_cause); - current_incompat_id = self.incompatibility_store.alloc(prior_cause); - current_incompat_changed = true; - } - } - } - } - } - - /// Backtracking. - fn backtrack( - &mut self, - incompat: IncompId, - incompat_changed: bool, - decision_level: DecisionLevel, - ) { - self.partial_solution - .backtrack(decision_level, &self.incompatibility_store); - self.contradicted_incompatibilities.clear(); - if incompat_changed { - self.merge_incompatibility(incompat); - } - } - - /// Add this incompatibility into the set of all incompatibilities. - /// - /// Pub collapses identical dependencies from adjacent package versions - /// into individual incompatibilities. - /// This substantially reduces the total number of incompatibilities - /// and makes it much easier for Pub to reason about multiple versions of packages at once. - /// - /// For example, rather than representing - /// foo 1.0.0 depends on bar ^1.0.0 and - /// foo 1.1.0 depends on bar ^1.0.0 - /// as two separate incompatibilities, - /// they are collapsed together into the single incompatibility {foo ^1.0.0, not bar ^1.0.0} - /// (provided that no other version of foo exists between 1.0.0 and 2.0.0). - /// We could collapse them into { foo (1.0.0 ∪ 1.1.0), not bar ^1.0.0 } - /// without having to check the existence of other versions though. - /// - /// Here we do the simple stupid thing of just growing the Vec. - /// It may not be trivial since those incompatibilities - /// may already have derived others. - fn merge_incompatibility(&mut self, id: IncompId) { - for (pkg, term) in self.incompatibility_store[id].iter() { - if cfg!(debug_assertions) { - assert_ne!(term, &crate::term::Term::any()); - } - self.incompatibilities - .entry(pkg.clone()) - .or_default() - .push(id); - } - } - - // Error reporting ######################################################### - - fn build_derivation_tree(&self, incompat: IncompId) -> DerivationTree { - let shared_ids = self.find_shared_ids(incompat); - Incompatibility::build_derivation_tree(incompat, &shared_ids, &self.incompatibility_store) - } - - fn find_shared_ids(&self, incompat: IncompId) -> Set> { - let mut all_ids = Set::new(); - let mut shared_ids = Set::new(); - let mut stack = vec![incompat]; - while let Some(i) = stack.pop() { - if let Some((id1, id2)) = self.incompatibility_store[i].causes() { - if all_ids.contains(&i) { - shared_ids.insert(i); - } else { - all_ids.insert(i); - stack.push(id1); - stack.push(id2); - } - } - } - shared_ids - } -} diff --git a/vendor/pubgrub/src/internal/incompatibility.rs b/vendor/pubgrub/src/internal/incompatibility.rs deleted file mode 100644 index 168c5218c..000000000 --- a/vendor/pubgrub/src/internal/incompatibility.rs +++ /dev/null @@ -1,300 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! An incompatibility is a set of terms for different packages -//! that should never be satisfied all together. - -use std::collections::HashSet as Set; -use std::fmt; - -use crate::internal::arena::{Arena, Id}; -use crate::internal::small_map::SmallMap; -use crate::package::Package; -use crate::report::{DefaultStringReporter, DerivationTree, Derived, External}; -use crate::term::{self, Term}; -use crate::version_set::VersionSet; - -/// An incompatibility is a set of terms for different packages -/// that should never be satisfied all together. -/// An incompatibility usually originates from a package dependency. -/// For example, if package A at version 1 depends on package B -/// at version 2, you can never have both terms `A = 1` -/// and `not B = 2` satisfied at the same time in a partial solution. -/// This would mean that we found a solution with package A at version 1 -/// but not with package B at version 2. -/// Yet A at version 1 depends on B at version 2 so this is not possible. -/// Therefore, the set `{ A = 1, not B = 2 }` is an incompatibility, -/// defined from dependencies of A at version 1. -/// -/// Incompatibilities can also be derived from two other incompatibilities -/// during conflict resolution. More about all this in -/// [PubGrub documentation](https://github.com/dart-lang/pub/blob/master/doc/solver.md#incompatibility). -#[derive(Debug, Clone)] -pub struct Incompatibility { - package_terms: SmallMap>, - pub kind: Kind, -} - -/// Type alias of unique identifiers for incompatibilities. -pub type IncompId = Id>; - -#[derive(Debug, Clone)] -pub enum Kind { - /// Initial incompatibility aiming at picking the root package for the first decision. - NotRoot(P, VS::V), - /// There are no versions in the given range for this package. - NoVersions(P, VS), - /// Dependencies of the package are unavailable for versions in that range. - UnavailableDependencies(P, VS), - /// Incompatibility coming from the dependencies of a given package. - FromDependencyOf(P, VS, P, VS), - /// Derived from two causes. Stores cause ids. - DerivedFrom(IncompId, IncompId), -} - -/// A Relation describes how a set of terms can be compared to an incompatibility. -/// Typically, the set of terms comes from the partial solution. -#[derive(Eq, PartialEq, Debug)] -pub enum Relation { - /// We say that a set of terms S satisfies an incompatibility I - /// if S satisfies every term in I. - Satisfied, - /// We say that S contradicts I - /// if S contradicts at least one term in I. - Contradicted(P), - /// If S satisfies all but one of I's terms and is inconclusive for the remaining term, - /// we say S "almost satisfies" I and we call the remaining term the "unsatisfied term". - AlmostSatisfied(P), - /// Otherwise, we say that their relation is inconclusive. - Inconclusive, -} - -impl Incompatibility { - /// Create the initial "not Root" incompatibility. - pub fn not_root(package: P, version: VS::V) -> Self { - Self { - package_terms: SmallMap::One([( - package.clone(), - Term::Negative(VS::singleton(version.clone())), - )]), - kind: Kind::NotRoot(package, version), - } - } - - /// Create an incompatibility to remember - /// that a given set does not contain any version. - pub fn no_versions(package: P, term: Term) -> Self { - let set = match &term { - Term::Positive(r) => r.clone(), - Term::Negative(_) => panic!("No version should have a positive term"), - }; - Self { - package_terms: SmallMap::One([(package.clone(), term)]), - kind: Kind::NoVersions(package, set), - } - } - - /// Create an incompatibility to remember - /// that a package version is not selectable - /// because its list of dependencies is unavailable. - pub fn unavailable_dependencies(package: P, version: VS::V) -> Self { - let set = VS::singleton(version); - Self { - package_terms: SmallMap::One([(package.clone(), Term::Positive(set.clone()))]), - kind: Kind::UnavailableDependencies(package, set), - } - } - - /// Build an incompatibility from a given dependency. - pub fn from_dependency(package: P, version: VS::V, dep: (&P, &VS)) -> Self { - let set1 = VS::singleton(version); - let (p2, set2) = dep; - Self { - package_terms: if set2 == &VS::empty() { - SmallMap::One([(package.clone(), Term::Positive(set1.clone()))]) - } else { - SmallMap::Two([ - (package.clone(), Term::Positive(set1.clone())), - (p2.clone(), Term::Negative(set2.clone())), - ]) - }, - kind: Kind::FromDependencyOf(package, set1, p2.clone(), set2.clone()), - } - } - - /// Prior cause of two incompatibilities using the rule of resolution. - pub fn prior_cause( - incompat: Id, - satisfier_cause: Id, - package: &P, - incompatibility_store: &Arena, - ) -> Self { - let kind = Kind::DerivedFrom(incompat, satisfier_cause); - let mut package_terms = incompatibility_store[incompat].package_terms.clone(); - let t1 = package_terms.remove(package).unwrap(); - let satisfier_cause_terms = &incompatibility_store[satisfier_cause].package_terms; - package_terms.merge( - satisfier_cause_terms.iter().filter(|(p, _)| p != &package), - |t1, t2| Some(t1.intersection(t2)), - ); - let term = t1.union(satisfier_cause_terms.get(package).unwrap()); - if term != Term::any() { - package_terms.insert(package.clone(), term); - } - Self { - package_terms, - kind, - } - } - - /// Check if an incompatibility should mark the end of the algorithm - /// because it satisfies the root package. - pub fn is_terminal(&self, root_package: &P, root_version: &VS::V) -> bool { - if self.package_terms.len() == 0 { - true - } else if self.package_terms.len() > 1 { - false - } else { - let (package, term) = self.package_terms.iter().next().unwrap(); - (package == root_package) && term.contains(root_version) - } - } - - /// Get the term related to a given package (if it exists). - pub fn get(&self, package: &P) -> Option<&Term> { - self.package_terms.get(package) - } - - /// Iterate over packages. - pub fn iter(&self) -> impl Iterator)> { - self.package_terms.iter() - } - - // Reporting ############################################################### - - /// Retrieve parent causes if of type DerivedFrom. - pub fn causes(&self) -> Option<(Id, Id)> { - match self.kind { - Kind::DerivedFrom(id1, id2) => Some((id1, id2)), - _ => None, - } - } - - /// Build a derivation tree for error reporting. - pub fn build_derivation_tree( - self_id: Id, - shared_ids: &Set>, - store: &Arena, - ) -> DerivationTree { - match &store[self_id].kind { - Kind::DerivedFrom(id1, id2) => { - let cause1 = Self::build_derivation_tree(*id1, shared_ids, store); - let cause2 = Self::build_derivation_tree(*id2, shared_ids, store); - let derived = Derived { - terms: store[self_id].package_terms.as_map(), - shared_id: shared_ids.get(&self_id).map(|id| id.into_raw()), - cause1: Box::new(cause1), - cause2: Box::new(cause2), - }; - DerivationTree::Derived(derived) - } - Kind::NotRoot(package, version) => { - DerivationTree::External(External::NotRoot(package.clone(), version.clone())) - } - Kind::NoVersions(package, set) => { - DerivationTree::External(External::NoVersions(package.clone(), set.clone())) - } - Kind::UnavailableDependencies(package, set) => DerivationTree::External( - External::UnavailableDependencies(package.clone(), set.clone()), - ), - Kind::FromDependencyOf(package, set, dep_package, dep_set) => { - DerivationTree::External(External::FromDependencyOf( - package.clone(), - set.clone(), - dep_package.clone(), - dep_set.clone(), - )) - } - } - } -} - -impl<'a, P: Package, VS: VersionSet + 'a> Incompatibility { - /// CF definition of Relation enum. - pub fn relation(&self, terms: impl Fn(&P) -> Option<&'a Term>) -> Relation

{ - let mut relation = Relation::Satisfied; - for (package, incompat_term) in self.package_terms.iter() { - match terms(package).map(|term| incompat_term.relation_with(term)) { - Some(term::Relation::Satisfied) => {} - Some(term::Relation::Contradicted) => { - return Relation::Contradicted(package.clone()); - } - None | Some(term::Relation::Inconclusive) => { - // If a package is not present, the intersection is the same as [Term::any]. - // According to the rules of satisfactions, the relation would be inconclusive. - // It could also be satisfied if the incompatibility term was also [Term::any], - // but we systematically remove those from incompatibilities - // so we're safe on that front. - if relation == Relation::Satisfied { - relation = Relation::AlmostSatisfied(package.clone()); - } else { - relation = Relation::Inconclusive; - } - } - } - } - relation - } -} - -impl fmt::Display for Incompatibility { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{}", - DefaultStringReporter::string_terms(&self.package_terms.as_map()) - ) - } -} - -// TESTS ####################################################################### - -#[cfg(test)] -pub mod tests { - use super::*; - use crate::range::Range; - use crate::term::tests::strategy as term_strat; - use crate::type_aliases::Map; - use proptest::prelude::*; - - proptest! { - - /// For any three different packages p1, p2 and p3, - /// for any three terms t1, t2 and t3, - /// if we have the two following incompatibilities: - /// { p1: t1, p2: not t2 } - /// { p2: t2, p3: t3 } - /// the rule of resolution says that we can deduce the following incompatibility: - /// { p1: t1, p3: t3 } - #[test] - fn rule_of_resolution(t1 in term_strat(), t2 in term_strat(), t3 in term_strat()) { - let mut store = Arena::new(); - let i1 = store.alloc(Incompatibility { - package_terms: SmallMap::Two([("p1", t1.clone()), ("p2", t2.negate())]), - kind: Kind::UnavailableDependencies("0", Range::full()) - }); - - let i2 = store.alloc(Incompatibility { - package_terms: SmallMap::Two([("p2", t2), ("p3", t3.clone())]), - kind: Kind::UnavailableDependencies("0", Range::full()) - }); - - let mut i3 = Map::default(); - i3.insert("p1", t1); - i3.insert("p3", t3); - - let i_resolution = Incompatibility::prior_cause(i1, i2, &"p2", &store); - assert_eq!(i_resolution.package_terms.as_map(), i3); - } - - } -} diff --git a/vendor/pubgrub/src/internal/mod.rs b/vendor/pubgrub/src/internal/mod.rs deleted file mode 100644 index 86d7e22e0..000000000 --- a/vendor/pubgrub/src/internal/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Non exposed modules. - -pub mod arena; -pub mod core; -pub mod incompatibility; -pub mod partial_solution; -pub mod small_map; -pub mod small_vec; diff --git a/vendor/pubgrub/src/internal/partial_solution.rs b/vendor/pubgrub/src/internal/partial_solution.rs deleted file mode 100644 index 6a8a2bff5..000000000 --- a/vendor/pubgrub/src/internal/partial_solution.rs +++ /dev/null @@ -1,591 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! A Memory acts like a structured partial solution -//! where terms are regrouped by package in a [Map](crate::type_aliases::Map). - -use std::fmt::Display; -use std::hash::BuildHasherDefault; - -use priority_queue::PriorityQueue; -use rustc_hash::FxHasher; - -use crate::internal::arena::Arena; -use crate::internal::incompatibility::{IncompId, Incompatibility, Relation}; -use crate::internal::small_map::SmallMap; -use crate::package::Package; -use crate::term::Term; -use crate::type_aliases::SelectedDependencies; -use crate::version_set::VersionSet; - -use super::small_vec::SmallVec; - -type FnvIndexMap = indexmap::IndexMap>; - -#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)] -pub struct DecisionLevel(pub u32); - -impl DecisionLevel { - pub fn increment(self) -> Self { - Self(self.0 + 1) - } -} - -/// The partial solution contains all package assignments, -/// organized by package and historically ordered. -#[derive(Clone, Debug)] -pub struct PartialSolution { - next_global_index: u32, - current_decision_level: DecisionLevel, - /// `package_assignments` is primarily a HashMap from a package to its - /// `PackageAssignments`. But it can also keep the items in an order. - /// We maintain three sections in this order: - /// 1. `[..current_decision_level]` Are packages that have had a decision made sorted by the `decision_level`. - /// This makes it very efficient to extract the solution, And to backtrack to a particular decision level. - /// 2. `[current_decision_level..changed_this_decision_level]` Are packages that have **not** had there assignments - /// changed since the last time `prioritize` has bean called. Within this range there is no sorting. - /// 3. `[changed_this_decision_level..]` Containes all packages that **have** had there assignments changed since - /// the last time `prioritize` has bean called. The inverse is not necessarily true, some packages in the range - /// did not have a change. Within this range there is no sorting. - package_assignments: FnvIndexMap>, - /// `prioritized_potential_packages` is primarily a HashMap from a package with no desition and a positive assignment - /// to its `Priority`. But, it also maintains a max heap of packages by `Priority` order. - prioritized_potential_packages: PriorityQueue>, - changed_this_decision_level: usize, -} - -impl Display - for PartialSolution -{ - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let mut assignments: Vec<_> = self - .package_assignments - .iter() - .map(|(p, pa)| format!("{}: {}", p, pa)) - .collect(); - assignments.sort(); - write!( - f, - "next_global_index: {}\ncurrent_decision_level: {:?}\npackage_assignements:\n{}", - self.next_global_index, - self.current_decision_level, - assignments.join("\t\n") - ) - } -} - -/// Package assignments contain the potential decision and derivations -/// that have already been made for a given package, -/// as well as the intersection of terms by all of these. -#[derive(Clone, Debug)] -struct PackageAssignments { - smallest_decision_level: DecisionLevel, - highest_decision_level: DecisionLevel, - dated_derivations: SmallVec>, - assignments_intersection: AssignmentsIntersection, -} - -impl Display for PackageAssignments { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let derivations: Vec<_> = self - .dated_derivations - .iter() - .map(|dd| dd.to_string()) - .collect(); - write!( - f, - "decision range: {:?}..{:?}\nderivations:\n {}\n,assignments_intersection: {}", - self.smallest_decision_level, - self.highest_decision_level, - derivations.join("\n "), - self.assignments_intersection - ) - } -} - -#[derive(Clone, Debug)] -pub struct DatedDerivation { - global_index: u32, - decision_level: DecisionLevel, - cause: IncompId, -} - -impl Display for DatedDerivation { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}, cause: {:?}", self.decision_level, self.cause) - } -} - -#[derive(Clone, Debug)] -enum AssignmentsIntersection { - Decision((u32, VS::V, Term)), - Derivations(Term), -} - -impl Display for AssignmentsIntersection { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Decision((lvl, version, _)) => { - write!(f, "Decision: level {}, v = {}", lvl, version) - } - Self::Derivations(term) => write!(f, "Derivations term: {}", term), - } - } -} - -#[derive(Clone, Debug)] -pub enum SatisfierSearch { - DifferentDecisionLevels { - previous_satisfier_level: DecisionLevel, - }, - SameDecisionLevels { - satisfier_cause: IncompId, - }, -} - -impl PartialSolution { - /// Initialize an empty PartialSolution. - pub fn empty() -> Self { - Self { - next_global_index: 0, - current_decision_level: DecisionLevel(0), - package_assignments: FnvIndexMap::default(), - prioritized_potential_packages: PriorityQueue::default(), - changed_this_decision_level: 0, - } - } - - /// Add a decision. - pub fn add_decision(&mut self, package: P, version: VS::V) { - // Check that add_decision is never used in the wrong context. - if cfg!(debug_assertions) { - match self.package_assignments.get_mut(&package) { - None => panic!("Derivations must already exist"), - Some(pa) => match &pa.assignments_intersection { - // Cannot be called when a decision has already been taken. - AssignmentsIntersection::Decision(_) => panic!("Already existing decision"), - // Cannot be called if the versions is not contained in the terms intersection. - AssignmentsIntersection::Derivations(term) => { - debug_assert!( - term.contains(&version), - "{}: {} was expected to be contained in {}", - package, - version, - term, - ) - } - }, - } - assert_eq!( - self.changed_this_decision_level, - self.package_assignments.len() - ); - } - let new_idx = self.current_decision_level.0 as usize; - self.current_decision_level = self.current_decision_level.increment(); - let (old_idx, _, pa) = self - .package_assignments - .get_full_mut(&package) - .expect("Derivations must already exist"); - pa.highest_decision_level = self.current_decision_level; - pa.assignments_intersection = AssignmentsIntersection::Decision(( - self.next_global_index, - version.clone(), - Term::exact(version), - )); - // Maintain that the beginning of the `package_assignments` Have all decisions in sorted order. - if new_idx != old_idx { - self.package_assignments.swap_indices(new_idx, old_idx); - } - self.next_global_index += 1; - } - - /// Add a derivation. - pub fn add_derivation( - &mut self, - package: P, - cause: IncompId, - store: &Arena>, - ) { - use indexmap::map::Entry; - let term = store[cause].get(&package).unwrap().negate(); - let dated_derivation = DatedDerivation { - global_index: self.next_global_index, - decision_level: self.current_decision_level, - cause, - }; - self.next_global_index += 1; - let pa_last_index = self.package_assignments.len().saturating_sub(1); - match self.package_assignments.entry(package) { - Entry::Occupied(mut occupied) => { - let idx = occupied.index(); - let pa = occupied.get_mut(); - pa.highest_decision_level = self.current_decision_level; - match &mut pa.assignments_intersection { - // Check that add_derivation is never called in the wrong context. - AssignmentsIntersection::Decision(_) => { - panic!("add_derivation should not be called after a decision") - } - AssignmentsIntersection::Derivations(t) => { - *t = t.intersection(&term); - if t.is_positive() { - // we can use `swap_indices` to make `changed_this_decision_level` only go down by 1 - // but the copying is slower then the larger search - self.changed_this_decision_level = - std::cmp::min(self.changed_this_decision_level, idx); - } - } - } - pa.dated_derivations.push(dated_derivation); - } - Entry::Vacant(v) => { - if term.is_positive() { - self.changed_this_decision_level = - std::cmp::min(self.changed_this_decision_level, pa_last_index); - } - v.insert(PackageAssignments { - smallest_decision_level: self.current_decision_level, - highest_decision_level: self.current_decision_level, - dated_derivations: SmallVec::One([dated_derivation]), - assignments_intersection: AssignmentsIntersection::Derivations(term), - }); - } - } - } - - pub fn prioritized_packages(&self) -> impl Iterator { - let check_all = self.changed_this_decision_level - == self.current_decision_level.0.saturating_sub(1) as usize; - let current_decision_level = self.current_decision_level; - self.package_assignments - .get_range(self.changed_this_decision_level..) - .unwrap() - .iter() - .filter(move |(_, pa)| { - // We only actually need to update the package if its Been changed - // since the last time we called prioritize. - // Which means it's highest decision level is the current decision level, - // or if we backtracked in the mean time. - check_all || pa.highest_decision_level == current_decision_level - }) - .filter_map(|(p, pa)| pa.assignments_intersection.potential_package_filter(p)) - } - - pub fn pick_highest_priority_pkg( - &mut self, - prioritizer: impl Fn(&P, &VS) -> Priority, - ) -> Option

{ - let check_all = self.changed_this_decision_level - == self.current_decision_level.0.saturating_sub(1) as usize; - let current_decision_level = self.current_decision_level; - let prioritized_potential_packages = &mut self.prioritized_potential_packages; - self.package_assignments - .get_range(self.changed_this_decision_level..) - .unwrap() - .iter() - .filter(|(_, pa)| { - // We only actually need to update the package if its Been changed - // since the last time we called prioritize. - // Which means it's highest decision level is the current decision level, - // or if we backtracked in the mean time. - check_all || pa.highest_decision_level == current_decision_level - }) - .filter_map(|(p, pa)| pa.assignments_intersection.potential_package_filter(p)) - .for_each(|(p, r)| { - let priority = prioritizer(p, r); - prioritized_potential_packages.push(p.clone(), priority); - }); - self.changed_this_decision_level = self.package_assignments.len(); - prioritized_potential_packages.pop().map(|(p, _)| p) - } - - /// If a partial solution has, for every positive derivation, - /// a corresponding decision that satisfies that assignment, - /// it's a total solution and version solving has succeeded. - pub fn extract_solution(&self) -> SelectedDependencies { - self.package_assignments - .iter() - .take(self.current_decision_level.0 as usize) - .map(|(p, pa)| match &pa.assignments_intersection { - AssignmentsIntersection::Decision((_, v, _)) => (p.clone(), v.clone()), - AssignmentsIntersection::Derivations(_) => { - panic!("Derivations in the Decision part") - } - }) - .collect() - } - - /// Backtrack the partial solution to a given decision level. - pub fn backtrack( - &mut self, - decision_level: DecisionLevel, - store: &Arena>, - ) { - self.current_decision_level = decision_level; - self.package_assignments.retain(|p, pa| { - if pa.smallest_decision_level > decision_level { - // Remove all entries that have a smallest decision level higher than the backtrack target. - false - } else if pa.highest_decision_level <= decision_level { - // Do not change entries older than the backtrack decision level target. - true - } else { - // smallest_decision_level <= decision_level < highest_decision_level - // - // Since decision_level < highest_decision_level, - // We can be certain that there will be no decision in this package assignments - // after backtracking, because such decision would have been the last - // assignment and it would have the "highest_decision_level". - - // Truncate the history. - while pa.dated_derivations.last().map(|dd| dd.decision_level) > Some(decision_level) - { - pa.dated_derivations.pop(); - } - debug_assert!(!pa.dated_derivations.is_empty()); - - // Update highest_decision_level. - pa.highest_decision_level = pa.dated_derivations.last().unwrap().decision_level; - - // Recompute the assignments intersection. - pa.assignments_intersection = AssignmentsIntersection::Derivations( - pa.dated_derivations - .iter() - .fold(Term::any(), |acc, dated_derivation| { - let term = store[dated_derivation.cause].get(p).unwrap().negate(); - acc.intersection(&term) - }), - ); - true - } - }); - // Throw away all stored priority levels, And mark that they all need to be recomputed. - self.prioritized_potential_packages.clear(); - self.changed_this_decision_level = self.current_decision_level.0.saturating_sub(1) as usize; - } - - /// We can add the version to the partial solution as a decision - /// if it doesn't produce any conflict with the new incompatibilities. - /// In practice I think it can only produce a conflict if one of the dependencies - /// (which are used to make the new incompatibilities) - /// is already in the partial solution with an incompatible version. - pub fn add_version( - &mut self, - package: P, - version: VS::V, - new_incompatibilities: std::ops::Range>, - store: &Arena>, - ) { - let exact = Term::exact(version.clone()); - let not_satisfied = |incompat: &Incompatibility| { - incompat.relation(|p| { - if p == &package { - Some(&exact) - } else { - self.term_intersection_for_package(p) - } - }) != Relation::Satisfied - }; - - // Check none of the dependencies (new_incompatibilities) - // would create a conflict (be satisfied). - if store[new_incompatibilities].iter().all(not_satisfied) { - log::info!("add_decision: {} @ {}", package, version); - self.add_decision(package, version); - } else { - log::info!( - "not adding {} @ {} because of its dependencies", - package, - version - ); - } - } - - /// Check if the terms in the partial solution satisfy the incompatibility. - pub fn relation(&self, incompat: &Incompatibility) -> Relation

{ - incompat.relation(|package| self.term_intersection_for_package(package)) - } - - /// Retrieve intersection of terms related to package. - pub fn term_intersection_for_package(&self, package: &P) -> Option<&Term> { - self.package_assignments - .get(package) - .map(|pa| pa.assignments_intersection.term()) - } - - /// Figure out if the satisfier and previous satisfier are of different decision levels. - pub fn satisfier_search( - &self, - incompat: &Incompatibility, - store: &Arena>, - ) -> (P, SatisfierSearch) { - let satisfied_map = Self::find_satisfier(incompat, &self.package_assignments, store); - let (satisfier_package, &(satisfier_index, _, satisfier_decision_level)) = satisfied_map - .iter() - .max_by_key(|(_p, (_, global_index, _))| global_index) - .unwrap(); - let satisfier_package = satisfier_package.clone(); - let previous_satisfier_level = Self::find_previous_satisfier( - incompat, - &satisfier_package, - satisfied_map, - &self.package_assignments, - store, - ); - if previous_satisfier_level < satisfier_decision_level { - let search_result = SatisfierSearch::DifferentDecisionLevels { - previous_satisfier_level, - }; - (satisfier_package, search_result) - } else { - let satisfier_pa = self.package_assignments.get(&satisfier_package).unwrap(); - let dd = &satisfier_pa.dated_derivations[satisfier_index]; - let search_result = SatisfierSearch::SameDecisionLevels { - satisfier_cause: dd.cause, - }; - (satisfier_package, search_result) - } - } - - /// A satisfier is the earliest assignment in partial solution such that the incompatibility - /// is satisfied by the partial solution up to and including that assignment. - /// - /// Returns a map indicating for each package term, when that was first satisfied in history. - /// If we effectively found a satisfier, the returned map must be the same size that incompat. - /// - /// Question: This is possible since we added a "global_index" to every dated_derivation. - /// It would be nice if we could get rid of it, but I don't know if then it will be possible - /// to return a coherent previous_satisfier_level. - fn find_satisfier( - incompat: &Incompatibility, - package_assignments: &FnvIndexMap>, - store: &Arena>, - ) -> SmallMap { - let mut satisfied = SmallMap::Empty; - for (package, incompat_term) in incompat.iter() { - let pa = package_assignments.get(package).expect("Must exist"); - satisfied.insert( - package.clone(), - pa.satisfier(package, incompat_term, Term::any(), store), - ); - } - satisfied - } - - /// Earliest assignment in the partial solution before satisfier - /// such that incompatibility is satisfied by the partial solution up to - /// and including that assignment plus satisfier. - fn find_previous_satisfier( - incompat: &Incompatibility, - satisfier_package: &P, - mut satisfied_map: SmallMap, - package_assignments: &FnvIndexMap>, - store: &Arena>, - ) -> DecisionLevel { - // First, let's retrieve the previous derivations and the initial accum_term. - let satisfier_pa = package_assignments.get(satisfier_package).unwrap(); - let (satisfier_index, _gidx, _dl) = satisfied_map.get_mut(satisfier_package).unwrap(); - - let accum_term = if *satisfier_index == satisfier_pa.dated_derivations.len() { - match &satisfier_pa.assignments_intersection { - AssignmentsIntersection::Derivations(_) => panic!("must be a decision"), - AssignmentsIntersection::Decision((_, _, term)) => term.clone(), - } - } else { - let dd = &satisfier_pa.dated_derivations[*satisfier_index]; - store[dd.cause].get(satisfier_package).unwrap().negate() - }; - - let incompat_term = incompat - .get(satisfier_package) - .expect("satisfier package not in incompat"); - - satisfied_map.insert( - satisfier_package.clone(), - satisfier_pa.satisfier(satisfier_package, incompat_term, accum_term, store), - ); - - // Finally, let's identify the decision level of that previous satisfier. - let (_, &(_, _, decision_level)) = satisfied_map - .iter() - .max_by_key(|(_p, (_, global_index, _))| global_index) - .unwrap(); - decision_level.max(DecisionLevel(1)) - } -} - -impl PackageAssignments { - fn satisfier( - &self, - package: &P, - incompat_term: &Term, - start_term: Term, - store: &Arena>, - ) -> (usize, u32, DecisionLevel) { - // Term where we accumulate intersections until incompat_term is satisfied. - let mut accum_term = start_term; - // Indicate if we found a satisfier in the list of derivations, otherwise it will be the decision. - for (idx, dated_derivation) in self.dated_derivations.iter().enumerate() { - let this_term = store[dated_derivation.cause].get(package).unwrap().negate(); - accum_term = accum_term.intersection(&this_term); - if accum_term.subset_of(incompat_term) { - // We found the derivation causing satisfaction. - return ( - idx, - dated_derivation.global_index, - dated_derivation.decision_level, - ); - } - } - // If it wasn't found in the derivations, - // it must be the decision which is last (if called in the right context). - match self.assignments_intersection { - AssignmentsIntersection::Decision((global_index, _, _)) => ( - self.dated_derivations.len(), - global_index, - self.highest_decision_level, - ), - AssignmentsIntersection::Derivations(_) => { - unreachable!( - concat!( - "while processing package {}: ", - "accum_term = {} isn't a subset of incompat_term = {}, ", - "which means the last assignment should have been a decision, ", - "but instead it was a derivation. This shouldn't be possible! ", - "(Maybe your Version ordering is broken?)" - ), - package, accum_term, incompat_term - ) - } - } - } -} - -impl AssignmentsIntersection { - /// Returns the term intersection of all assignments (decision included). - fn term(&self) -> &Term { - match self { - Self::Decision((_, _, term)) => term, - Self::Derivations(term) => term, - } - } - - /// A package is a potential pick if there isn't an already - /// selected version (no "decision") - /// and if it contains at least one positive derivation term - /// in the partial solution. - fn potential_package_filter<'a, P: Package>( - &'a self, - package: &'a P, - ) -> Option<(&'a P, &'a VS)> { - match self { - Self::Decision(_) => None, - Self::Derivations(term_intersection) => { - if term_intersection.is_positive() { - Some((package, term_intersection.unwrap_positive())) - } else { - None - } - } - } - } -} diff --git a/vendor/pubgrub/src/internal/small_map.rs b/vendor/pubgrub/src/internal/small_map.rs deleted file mode 100644 index a1fe5f9e5..000000000 --- a/vendor/pubgrub/src/internal/small_map.rs +++ /dev/null @@ -1,195 +0,0 @@ -use crate::type_aliases::Map; -use std::hash::Hash; - -#[derive(Debug, Clone)] -pub enum SmallMap { - Empty, - One([(K, V); 1]), - Two([(K, V); 2]), - Flexible(Map), -} - -impl SmallMap { - pub fn get(&self, key: &K) -> Option<&V> { - match self { - Self::Empty => None, - Self::One([(k, v)]) if k == key => Some(v), - Self::One(_) => None, - Self::Two([(k1, v1), _]) if key == k1 => Some(v1), - Self::Two([_, (k2, v2)]) if key == k2 => Some(v2), - Self::Two(_) => None, - Self::Flexible(data) => data.get(key), - } - } - - pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { - match self { - Self::Empty => None, - Self::One([(k, v)]) if k == key => Some(v), - Self::One(_) => None, - Self::Two([(k1, v1), _]) if key == k1 => Some(v1), - Self::Two([_, (k2, v2)]) if key == k2 => Some(v2), - Self::Two(_) => None, - Self::Flexible(data) => data.get_mut(key), - } - } - - pub fn remove(&mut self, key: &K) -> Option { - let out; - *self = match std::mem::take(self) { - Self::Empty => { - out = None; - Self::Empty - } - Self::One([(k, v)]) => { - if key == &k { - out = Some(v); - Self::Empty - } else { - out = None; - Self::One([(k, v)]) - } - } - Self::Two([(k1, v1), (k2, v2)]) => { - if key == &k1 { - out = Some(v1); - Self::One([(k2, v2)]) - } else if key == &k2 { - out = Some(v2); - Self::One([(k1, v1)]) - } else { - out = None; - Self::Two([(k1, v1), (k2, v2)]) - } - } - Self::Flexible(mut data) => { - out = data.remove(key); - Self::Flexible(data) - } - }; - out - } - - pub fn insert(&mut self, key: K, value: V) { - *self = match std::mem::take(self) { - Self::Empty => Self::One([(key, value)]), - Self::One([(k, v)]) => { - if key == k { - Self::One([(k, value)]) - } else { - Self::Two([(k, v), (key, value)]) - } - } - Self::Two([(k1, v1), (k2, v2)]) => { - if key == k1 { - Self::Two([(k1, value), (k2, v2)]) - } else if key == k2 { - Self::Two([(k1, v1), (k2, value)]) - } else { - let mut data: Map = Map::with_capacity_and_hasher(3, Default::default()); - data.insert(key, value); - data.insert(k1, v1); - data.insert(k2, v2); - Self::Flexible(data) - } - } - Self::Flexible(mut data) => { - data.insert(key, value); - Self::Flexible(data) - } - }; - } -} - -impl SmallMap { - /// Merge two hash maps. - /// - /// When a key is common to both, - /// apply the provided function to both values. - /// If the result is None, remove that key from the merged map, - /// otherwise add the content of the Some(_). - pub fn merge<'a>( - &'a mut self, - map_2: impl Iterator, - f: impl Fn(&V, &V) -> Option, - ) { - for (key, val_2) in map_2 { - match self.get_mut(key) { - None => { - self.insert(key.clone(), val_2.clone()); - } - Some(val_1) => match f(val_1, val_2) { - None => { - self.remove(key); - } - Some(merged_value) => *val_1 = merged_value, - }, - } - } - } -} - -impl Default for SmallMap { - fn default() -> Self { - Self::Empty - } -} - -impl SmallMap { - pub fn len(&self) -> usize { - match self { - Self::Empty => 0, - Self::One(_) => 1, - Self::Two(_) => 2, - Self::Flexible(data) => data.len(), - } - } -} - -impl SmallMap { - pub fn as_map(&self) -> Map { - match self { - Self::Empty => Map::default(), - Self::One([(k, v)]) => { - let mut map = Map::with_capacity_and_hasher(1, Default::default()); - map.insert(k.clone(), v.clone()); - map - } - Self::Two(data) => { - let mut map = Map::with_capacity_and_hasher(2, Default::default()); - for (k, v) in data { - map.insert(k.clone(), v.clone()); - } - map - } - Self::Flexible(data) => data.clone(), - } - } -} - -enum IterSmallMap<'a, K, V> { - Inline(std::slice::Iter<'a, (K, V)>), - Map(std::collections::hash_map::Iter<'a, K, V>), -} - -impl<'a, K: 'a, V: 'a> Iterator for IterSmallMap<'a, K, V> { - type Item = (&'a K, &'a V); - - fn next(&mut self) -> Option { - match self { - IterSmallMap::Inline(inner) => inner.next().map(|(k, v)| (k, v)), - IterSmallMap::Map(inner) => inner.next(), - } - } -} - -impl SmallMap { - pub fn iter(&self) -> impl Iterator { - match self { - Self::Empty => IterSmallMap::Inline([].iter()), - Self::One(data) => IterSmallMap::Inline(data.iter()), - Self::Two(data) => IterSmallMap::Inline(data.iter()), - Self::Flexible(data) => IterSmallMap::Map(data.iter()), - } - } -} diff --git a/vendor/pubgrub/src/internal/small_vec.rs b/vendor/pubgrub/src/internal/small_vec.rs deleted file mode 100644 index fa720435d..000000000 --- a/vendor/pubgrub/src/internal/small_vec.rs +++ /dev/null @@ -1,222 +0,0 @@ -use std::fmt; -use std::hash::{Hash, Hasher}; -use std::ops::Deref; - -#[derive(Clone)] -pub enum SmallVec { - Empty, - One([T; 1]), - Two([T; 2]), - Flexible(Vec), -} - -impl SmallVec { - pub fn empty() -> Self { - Self::Empty - } - - pub fn one(t: T) -> Self { - Self::One([t]) - } - - pub fn as_slice(&self) -> &[T] { - match self { - Self::Empty => &[], - Self::One(v) => v, - Self::Two(v) => v, - Self::Flexible(v) => v, - } - } - - pub fn push(&mut self, new: T) { - *self = match std::mem::take(self) { - Self::Empty => Self::One([new]), - Self::One([v1]) => Self::Two([v1, new]), - Self::Two([v1, v2]) => Self::Flexible(vec![v1, v2, new]), - Self::Flexible(mut v) => { - v.push(new); - Self::Flexible(v) - } - } - } - - pub fn pop(&mut self) -> Option { - match std::mem::take(self) { - Self::Empty => None, - Self::One([v1]) => { - *self = Self::Empty; - Some(v1) - } - Self::Two([v1, v2]) => { - *self = Self::One([v1]); - Some(v2) - } - Self::Flexible(mut v) => { - let out = v.pop(); - *self = Self::Flexible(v); - out - } - } - } - - pub fn clear(&mut self) { - if let Self::Flexible(mut v) = std::mem::take(self) { - v.clear(); - *self = Self::Flexible(v); - } // else: self already eq Empty from the take - } - - pub fn iter(&self) -> std::slice::Iter<'_, T> { - self.as_slice().iter() - } -} - -impl Default for SmallVec { - fn default() -> Self { - Self::Empty - } -} - -impl Deref for SmallVec { - type Target = [T]; - - fn deref(&self) -> &Self::Target { - self.as_slice() - } -} - -impl<'a, T> IntoIterator for &'a SmallVec { - type Item = &'a T; - - type IntoIter = std::slice::Iter<'a, T>; - - fn into_iter(self) -> Self::IntoIter { - self.iter() - } -} - -impl Eq for SmallVec {} - -impl PartialEq for SmallVec { - fn eq(&self, other: &Self) -> bool { - self.as_slice() == other.as_slice() - } -} - -impl fmt::Debug for SmallVec { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.as_slice().fmt(f) - } -} - -impl Hash for SmallVec { - fn hash(&self, state: &mut H) { - self.len().hash(state); - Hash::hash_slice(self.as_slice(), state); - } -} - -#[cfg(feature = "serde")] -impl serde::Serialize for SmallVec { - fn serialize(&self, s: S) -> Result { - serde::Serialize::serialize(self.as_slice(), s) - } -} - -#[cfg(feature = "serde")] -impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for SmallVec { - fn deserialize>(d: D) -> Result { - struct SmallVecVisitor { - marker: std::marker::PhantomData, - } - - impl<'de, T> serde::de::Visitor<'de> for SmallVecVisitor - where - T: serde::Deserialize<'de>, - { - type Value = SmallVec; - - fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str("a sequence") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - let mut values = SmallVec::empty(); - while let Some(value) = seq.next_element()? { - values.push(value); - } - Ok(values) - } - } - - let visitor = SmallVecVisitor { - marker: Default::default(), - }; - d.deserialize_seq(visitor) - } -} - -impl IntoIterator for SmallVec { - type Item = T; - type IntoIter = SmallVecIntoIter; - - fn into_iter(self) -> Self::IntoIter { - match self { - SmallVec::Empty => SmallVecIntoIter::Empty, - SmallVec::One(a) => SmallVecIntoIter::One(a.into_iter()), - SmallVec::Two(a) => SmallVecIntoIter::Two(a.into_iter()), - SmallVec::Flexible(v) => SmallVecIntoIter::Flexible(v.into_iter()), - } - } -} - -pub enum SmallVecIntoIter { - Empty, - One(<[T; 1] as IntoIterator>::IntoIter), - Two(<[T; 2] as IntoIterator>::IntoIter), - Flexible( as IntoIterator>::IntoIter), -} - -impl Iterator for SmallVecIntoIter { - type Item = T; - - fn next(&mut self) -> Option { - match self { - SmallVecIntoIter::Empty => None, - SmallVecIntoIter::One(it) => it.next(), - SmallVecIntoIter::Two(it) => it.next(), - SmallVecIntoIter::Flexible(it) => it.next(), - } - } -} - -// TESTS ####################################################################### - -#[cfg(test)] -pub mod tests { - use super::*; - use proptest::prelude::*; - - proptest! { - #[test] - fn push_and_pop(commands: Vec>) { - let mut v = vec![]; - let mut sv = SmallVec::Empty; - for command in commands { - match command { - Some(i) => { - v.push(i); - sv.push(i); - } - None => { - assert_eq!(v.pop(), sv.pop()); - } - } - assert_eq!(v.as_slice(), sv.as_slice()); - } - } - } -} diff --git a/vendor/pubgrub/src/lib.rs b/vendor/pubgrub/src/lib.rs deleted file mode 100644 index 0150c52ab..000000000 --- a/vendor/pubgrub/src/lib.rs +++ /dev/null @@ -1,232 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! PubGrub version solving algorithm. -//! -//! Version solving consists in efficiently finding a set of packages and versions -//! that satisfy all the constraints of a given project dependencies. -//! In addition, when that is not possible, -//! we should try to provide a very human-readable and clear -//! explanation as to why that failed. -//! -//! # Package and Version traits -//! -//! All the code in this crate is manipulating packages and versions, and for this to work -//! we defined a [Package](package::Package) and [Version](version::Version) traits -//! that are used as bounds on most of the exposed types and functions. -//! -//! Package identifiers needs to implement our [Package](package::Package) trait, -//! which is automatic if the type already implements -//! [Clone] + [Eq] + [Hash] + [Debug] + [Display](std::fmt::Display). -//! So things like [String] will work out of the box. -//! -//! Our [Version](version::Version) trait requires -//! [Clone] + [Ord] + [Debug] + [Display](std::fmt::Display) -//! and also the definition of two methods, -//! [lowest() -> Self](version::Version::lowest) which returns the lowest version existing, -//! and [bump(&self) -> Self](version::Version::bump) which returns the next smallest version -//! strictly higher than the current one. -//! For convenience, this library already provides -//! two implementations of [Version](version::Version). -//! The first one is [NumberVersion](version::NumberVersion), basically a newtype for [u32]. -//! The second one is [SemanticVersion](version::NumberVersion) -//! that implements semantic versioning rules. -//! -//! # Basic example -//! -//! Let's imagine that we are building a user interface -//! with a menu containing dropdowns with some icons, -//! icons that we are also directly using in other parts of the interface. -//! For this scenario our direct dependencies are `menu` and `icons`, -//! but the complete set of dependencies looks like follows: -//! -//! - `root` depends on `menu` and `icons` -//! - `menu` depends on `dropdown` -//! - `dropdown` depends on `icons` -//! - `icons` has no dependency -//! -//! We can model that scenario with this library as follows -//! ``` -//! # use pubgrub::solver::{OfflineDependencyProvider, resolve}; -//! # use pubgrub::version::NumberVersion; -//! # use pubgrub::range::Range; -//! -//! type NumVS = Range; -//! -//! let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new(); -//! -//! dependency_provider.add_dependencies( -//! "root", 1, [("menu", Range::full()), ("icons", Range::full())], -//! ); -//! dependency_provider.add_dependencies("menu", 1, [("dropdown", Range::full())]); -//! dependency_provider.add_dependencies("dropdown", 1, [("icons", Range::full())]); -//! dependency_provider.add_dependencies("icons", 1, []); -//! -//! // Run the algorithm. -//! let solution = resolve(&dependency_provider, "root", 1).unwrap(); -//! ``` -//! -//! # DependencyProvider trait -//! -//! In our previous example we used the -//! [OfflineDependencyProvider](solver::OfflineDependencyProvider), -//! which is a basic implementation of the [DependencyProvider](solver::DependencyProvider) trait. -//! -//! But we might want to implement the [DependencyProvider](solver::DependencyProvider) -//! trait for our own type. -//! Let's say that we will use [String] for packages, -//! and [SemanticVersion](version::SemanticVersion) for versions. -//! This may be done quite easily by implementing the three following functions. -//! ``` -//! # use pubgrub::solver::{DependencyProvider, Dependencies}; -//! # use pubgrub::version::SemanticVersion; -//! # use pubgrub::range::Range; -//! # use pubgrub::type_aliases::Map; -//! # use std::error::Error; -//! # use std::borrow::Borrow; -//! # -//! # struct MyDependencyProvider; -//! # -//! type SemVS = Range; -//! -//! impl DependencyProvider for MyDependencyProvider { -//! fn choose_version(&self, package: &String, range: &SemVS) -> Result, Box> { -//! unimplemented!() -//! } -//! -//! type Priority = usize; -//! fn prioritize(&self, package: &String, range: &SemVS) -> Self::Priority { -//! unimplemented!() -//! } -//! -//! fn get_dependencies( -//! &self, -//! package: &String, -//! version: &SemanticVersion, -//! ) -> Result, Box> { -//! unimplemented!() -//! } -//! } -//! ``` -//! -//! The first method -//! [choose_version](crate::solver::DependencyProvider::choose_version) -//! chooses a version compatible with the provided range for a package. -//! The second method -//! [prioritize](crate::solver::DependencyProvider::prioritize) -//! in which order different packages should be chosen. -//! Usually prioritizing packages -//! with the fewest number of compatible versions speeds up resolution. -//! But in general you are free to employ whatever strategy suits you best -//! to pick a package and a version. -//! -//! The third method [get_dependencies](crate::solver::DependencyProvider::get_dependencies) -//! aims at retrieving the dependencies of a given package at a given version. -//! Returns [None] if dependencies are unknown. -//! -//! In a real scenario, these two methods may involve reading the file system -//! or doing network request, so you may want to hold a cache in your -//! [DependencyProvider](solver::DependencyProvider) implementation. -//! How exactly this could be achieved is shown in `CachingDependencyProvider` -//! (see `examples/caching_dependency_provider.rs`). -//! You could also use the [OfflineDependencyProvider](solver::OfflineDependencyProvider) -//! type defined by the crate as guidance, -//! but you are free to use whatever approach makes sense in your situation. -//! -//! # Solution and error reporting -//! -//! When everything goes well, the algorithm finds and returns the complete -//! set of direct and indirect dependencies satisfying all the constraints. -//! The packages and versions selected are returned as -//! [SelectedDepedencies](type_aliases::SelectedDependencies). -//! But sometimes there is no solution because dependencies are incompatible. -//! In such cases, [resolve(...)](solver::resolve) returns a -//! [PubGrubError::NoSolution(derivation_tree)](error::PubGrubError::NoSolution), -//! where the provided derivation tree is a custom binary tree -//! containing the full chain of reasons why there is no solution. -//! -//! All the items in the tree are called incompatibilities -//! and may be of two types, either "external" or "derived". -//! Leaves of the tree are external incompatibilities, -//! and nodes are derived. -//! External incompatibilities have reasons that are independent -//! of the way this algorithm is implemented such as -//! - dependencies: "package_a" at version 1 depends on "package_b" at version 4 -//! - missing dependencies: dependencies of "package_a" are unknown -//! - absence of version: there is no version of "package_a" in the range [3.1.0 4.0.0[ -//! -//! Derived incompatibilities are obtained during the algorithm execution by deduction, -//! such as if "a" depends on "b" and "b" depends on "c", "a" depends on "c". -//! -//! This crate defines a [Reporter](crate::report::Reporter) trait, with an associated -//! [Output](crate::report::Reporter::Output) type and a single method. -//! ``` -//! # use pubgrub::package::Package; -//! # use pubgrub::version_set::VersionSet; -//! # use pubgrub::report::DerivationTree; -//! # -//! pub trait Reporter { -//! type Output; -//! -//! fn report(derivation_tree: &DerivationTree) -> Self::Output; -//! } -//! ``` -//! Implementing a [Reporter](crate::report::Reporter) may involve a lot of heuristics -//! to make the output human-readable and natural. -//! For convenience, we provide a default implementation -//! [DefaultStringReporter](crate::report::DefaultStringReporter) -//! that outputs the report as a [String]. -//! You may use it as follows: -//! ``` -//! # use pubgrub::solver::{resolve, OfflineDependencyProvider}; -//! # use pubgrub::report::{DefaultStringReporter, Reporter}; -//! # use pubgrub::error::PubGrubError; -//! # use pubgrub::version::NumberVersion; -//! # use pubgrub::range::Range; -//! # -//! # type NumVS = Range; -//! # -//! # let dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new(); -//! # let root_package = "root"; -//! # let root_version = 1; -//! # -//! match resolve(&dependency_provider, root_package, root_version) { -//! Ok(solution) => println!("{:?}", solution), -//! Err(PubGrubError::NoSolution(mut derivation_tree)) => { -//! derivation_tree.collapse_no_versions(); -//! eprintln!("{}", DefaultStringReporter::report(&derivation_tree)); -//! } -//! Err(err) => panic!("{:?}", err), -//! }; -//! ``` -//! Notice that we also used -//! [collapse_no_versions()](crate::report::DerivationTree::collapse_no_versions) above. -//! This method simplifies the derivation tree to get rid of the -//! [NoVersions](crate::report::External::NoVersions) -//! external incompatibilities in the derivation tree. -//! So instead of seeing things like this in the report: -//! ```txt -//! Because there is no version of foo in 1.0.1 <= v < 2.0.0 -//! and foo 1.0.0 depends on bar 2.0.0 <= v < 3.0.0, -//! foo 1.0.0 <= v < 2.0.0 depends on bar 2.0.0 <= v < 3.0.0. -//! ``` -//! you may have directly: -//! ```txt -//! foo 1.0.0 <= v < 2.0.0 depends on bar 2.0.0 <= v < 3.0.0. -//! ``` -//! Beware though that if you are using some kind of offline mode -//! with a cache, you may want to know that some versions -//! do not exist in your cache. - -#![allow(clippy::all, unreachable_pub)] - -pub mod error; -pub mod package; -pub mod range; -pub mod report; -pub mod solver; -pub mod term; -pub mod type_aliases; -pub mod version; -pub mod version_set; - -mod internal; diff --git a/vendor/pubgrub/src/package.rs b/vendor/pubgrub/src/package.rs deleted file mode 100644 index 36c6069e8..000000000 --- a/vendor/pubgrub/src/package.rs +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Trait for identifying packages. -//! Automatically implemented for traits implementing -//! [Clone] + [Eq] + [Hash] + [Debug] + [Display]. - -use std::fmt::{Debug, Display}; -use std::hash::Hash; - -/// Trait for identifying packages. -/// Automatically implemented for types already implementing -/// [Clone] + [Eq] + [Hash] + [Debug] + [Display]. -pub trait Package: Clone + Eq + Hash + Debug + Display {} - -/// Automatically implement the Package trait for any type -/// that already implement [Clone] + [Eq] + [Hash] + [Debug] + [Display]. -impl Package for T {} diff --git a/vendor/pubgrub/src/range.rs b/vendor/pubgrub/src/range.rs deleted file mode 100644 index 47e76e44f..000000000 --- a/vendor/pubgrub/src/range.rs +++ /dev/null @@ -1,613 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Ranges are constraints defining sets of versions. -//! -//! Concretely, those constraints correspond to any set of versions -//! representable as the concatenation, union, and complement -//! of the ranges building blocks. -//! -//! Those building blocks are: -//! - [empty()](Range::empty): the empty set -//! - [full()](Range::full): the set of all possible versions -//! - [singleton(v)](Range::singleton): the set containing only the version v -//! - [higher_than(v)](Range::higher_than): the set defined by `v <= versions` -//! - [strictly_higher_than(v)](Range::strictly_higher_than): the set defined by `v < versions` -//! - [lower_than(v)](Range::lower_than): the set defined by `versions <= v` -//! - [strictly_lower_than(v)](Range::strictly_lower_than): the set defined by `versions < v` -//! - [between(v1, v2)](Range::between): the set defined by `v1 <= versions < v2` -//! -//! Ranges can be created from any type that implements [`Ord`] + [`Clone`]. -//! -//! In order to advance the solver front, comparisons of versions sets are necessary in the algorithm. -//! To do those comparisons between two sets S1 and S2 we use the mathematical property that S1 āŠ‚ S2 if and only if S1 ∩ S2 == S1. -//! We can thus compute an intersection and evaluate an equality to answer if S1 is a subset of S2. -//! But this means that the implementation of equality must be correct semantically. -//! In practice, if equality is derived automatically, this means sets must have unique representations. -//! -//! By migrating from a custom representation for discrete sets in v0.2 -//! to a generic bounded representation for continuous sets in v0.3 -//! we are potentially breaking that assumption in two ways: -//! -//! 1. Minimal and maximal `Unbounded` values can be replaced by their equivalent if it exists. -//! 2. Simplifying adjacent bounds of discrete sets cannot be detected and automated in the generic intersection code. -//! -//! An example for each can be given when `T` is `u32`. -//! First, we can have both segments `S1 = (Unbounded, Included(42u32))` and `S2 = (Included(0), Included(42u32))` -//! that represent the same segment but are structurally different. -//! Thus, a derived equality check would answer `false` to `S1 == S2` while it's true. -//! -//! Second both segments `S1 = (Included(1), Included(5))` and `S2 = (Included(1), Included(3)) + (Included(4), Included(5))` are equal. -//! But without asking the user to provide a `bump` function for discrete sets, -//! the algorithm is not able tell that the space between the right `Included(3)` bound and the left `Included(4)` bound is empty. -//! Thus the algorithm is not able to reduce S2 to its canonical S1 form while computing sets operations like intersections in the generic code. -//! -//! This is likely to lead to user facing theoretically correct but practically nonsensical ranges, -//! like (Unbounded, Excluded(0)) or (Excluded(6), Excluded(7)). -//! In general nonsensical inputs often lead to hard to track bugs. -//! But as far as we can tell this should work in practice. -//! So for now this crate only provides an implementation for continuous ranges. -//! With the v0.3 api the user could choose to bring back the discrete implementation from v0.2, as documented in the guide. -//! If doing so regularly fixes bugs seen by users, we will bring it back into the core library. -//! If we do not see practical bugs, or we get a formal proof that the code cannot lead to error states, then we may remove this warning. - -use crate::{internal::small_vec::SmallVec, version_set::VersionSet}; -use std::ops::RangeBounds; -use std::{ - fmt::{Debug, Display, Formatter}, - ops::Bound::{self, Excluded, Included, Unbounded}, -}; - -/// A Range represents multiple intervals of a continuous range of monotone increasing -/// values. -#[derive(Debug, Clone, Eq, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize))] -#[cfg_attr(feature = "serde", serde(transparent))] -pub struct Range { - segments: SmallVec>, -} - -type Interval = (Bound, Bound); - -impl Range { - /// Empty set of versions. - pub fn empty() -> Self { - Self { - segments: SmallVec::empty(), - } - } - - /// Set of all possible versions - pub fn full() -> Self { - Self { - segments: SmallVec::one((Unbounded, Unbounded)), - } - } - - /// Set of all versions higher or equal to some version - pub fn higher_than(v: impl Into) -> Self { - Self { - segments: SmallVec::one((Included(v.into()), Unbounded)), - } - } - - /// Set of all versions higher to some version - pub fn strictly_higher_than(v: impl Into) -> Self { - Self { - segments: SmallVec::one((Excluded(v.into()), Unbounded)), - } - } - - /// Set of all versions lower to some version - pub fn strictly_lower_than(v: impl Into) -> Self { - Self { - segments: SmallVec::one((Unbounded, Excluded(v.into()))), - } - } - - /// Set of all versions lower or equal to some version - pub fn lower_than(v: impl Into) -> Self { - Self { - segments: SmallVec::one((Unbounded, Included(v.into()))), - } - } - - /// Set of versions greater or equal to `v1` but less than `v2`. - pub fn between(v1: impl Into, v2: impl Into) -> Self { - Self { - segments: SmallVec::one((Included(v1.into()), Excluded(v2.into()))), - } - } -} - -impl Range { - /// Set containing exactly one version - pub fn singleton(v: impl Into) -> Self { - let v = v.into(); - Self { - segments: SmallVec::one((Included(v.clone()), Included(v))), - } - } - - /// Returns the complement of this Range. - pub fn complement(&self) -> Self { - match self.segments.first() { - // Complement of āˆ… is āˆž - None => Self::full(), - - // Complement of āˆž is āˆ… - Some((Unbounded, Unbounded)) => Self::empty(), - - // First high bound is +āˆž - Some((Included(v), Unbounded)) => Self::strictly_lower_than(v.clone()), - Some((Excluded(v), Unbounded)) => Self::lower_than(v.clone()), - - Some((Unbounded, Included(v))) => { - Self::negate_segments(Excluded(v.clone()), &self.segments[1..]) - } - Some((Unbounded, Excluded(v))) => { - Self::negate_segments(Included(v.clone()), &self.segments[1..]) - } - Some((Included(_), Included(_))) - | Some((Included(_), Excluded(_))) - | Some((Excluded(_), Included(_))) - | Some((Excluded(_), Excluded(_))) => Self::negate_segments(Unbounded, &self.segments), - } - } - - /// Helper function performing the negation of intervals in segments. - fn negate_segments(start: Bound, segments: &[Interval]) -> Self { - let mut complement_segments: SmallVec> = SmallVec::empty(); - let mut start = start; - for (v1, v2) in segments { - complement_segments.push(( - start, - match v1 { - Included(v) => Excluded(v.clone()), - Excluded(v) => Included(v.clone()), - Unbounded => unreachable!(), - }, - )); - start = match v2 { - Included(v) => Excluded(v.clone()), - Excluded(v) => Included(v.clone()), - Unbounded => Unbounded, - } - } - if !matches!(start, Unbounded) { - complement_segments.push((start, Unbounded)); - } - - Self { - segments: complement_segments, - } - } -} - -impl Range { - /// Convert to something that can be used with - /// [BTreeMap::range](std::collections::BTreeMap::range). - /// All versions contained in self, will be in the output, - /// but there may be versions in the output that are not contained in self. - /// Returns None if the range is empty. - pub fn bounding_range(&self) -> Option<(Bound<&V>, Bound<&V>)> { - self.segments.first().map(|(start, _)| { - let end = self - .segments - .last() - .expect("if there is a first element, there must be a last element"); - (bound_as_ref(start), bound_as_ref(&end.1)) - }) - } - - /// Returns true if the this Range contains the specified value. - pub fn contains(&self, v: &V) -> bool { - for segment in self.segments.iter() { - if match segment { - (Unbounded, Unbounded) => true, - (Unbounded, Included(end)) => v <= end, - (Unbounded, Excluded(end)) => v < end, - (Included(start), Unbounded) => v >= start, - (Included(start), Included(end)) => v >= start && v <= end, - (Included(start), Excluded(end)) => v >= start && v < end, - (Excluded(start), Unbounded) => v > start, - (Excluded(start), Included(end)) => v > start && v <= end, - (Excluded(start), Excluded(end)) => v > start && v < end, - } { - return true; - } - } - false - } - - /// Construct a simple range from anything that impls [RangeBounds] like `v1..v2`. - pub fn from_range_bounds(bounds: R) -> Self - where - R: RangeBounds, - IV: Clone + Into, - { - let start = match bounds.start_bound() { - Included(v) => Included(v.clone().into()), - Excluded(v) => Excluded(v.clone().into()), - Unbounded => Unbounded, - }; - let end = match bounds.end_bound() { - Included(v) => Included(v.clone().into()), - Excluded(v) => Excluded(v.clone().into()), - Unbounded => Unbounded, - }; - if valid_segment(&start, &end) { - Self { - segments: SmallVec::one((start, end)), - } - } else { - Self::empty() - } - } - - fn check_invariants(self) -> Self { - if cfg!(debug_assertions) { - for p in self.segments.as_slice().windows(2) { - match (&p[0].1, &p[1].0) { - (Included(l_end), Included(r_start)) => assert!(l_end < r_start), - (Included(l_end), Excluded(r_start)) => assert!(l_end < r_start), - (Excluded(l_end), Included(r_start)) => assert!(l_end < r_start), - (Excluded(l_end), Excluded(r_start)) => assert!(l_end <= r_start), - (_, Unbounded) => panic!(), - (Unbounded, _) => panic!(), - } - } - for (s, e) in self.segments.iter() { - assert!(valid_segment(s, e)); - } - } - self - } -} - -/// Implementation of [`Bound::as_ref`] which is currently marked as unstable. -fn bound_as_ref(bound: &Bound) -> Bound<&V> { - match bound { - Included(v) => Included(v), - Excluded(v) => Excluded(v), - Unbounded => Unbounded, - } -} - -fn valid_segment(start: &Bound, end: &Bound) -> bool { - match (start, end) { - (Included(s), Included(e)) => s <= e, - (Included(s), Excluded(e)) => s < e, - (Excluded(s), Included(e)) => s < e, - (Excluded(s), Excluded(e)) => s < e, - (Unbounded, _) | (_, Unbounded) => true, - } -} - -impl Range { - /// Computes the union of this `Range` and another. - pub fn union(&self, other: &Self) -> Self { - self.complement() - .intersection(&other.complement()) - .complement() - .check_invariants() - } - - /// Computes the intersection of two sets of versions. - pub fn intersection(&self, other: &Self) -> Self { - let mut segments: SmallVec> = SmallVec::empty(); - let mut left_iter = self.segments.iter().peekable(); - let mut right_iter = other.segments.iter().peekable(); - - while let (Some((left_start, left_end)), Some((right_start, right_end))) = - (left_iter.peek(), right_iter.peek()) - { - let start = match (left_start, right_start) { - (Included(l), Included(r)) => Included(std::cmp::max(l, r)), - (Excluded(l), Excluded(r)) => Excluded(std::cmp::max(l, r)), - - (Included(i), Excluded(e)) | (Excluded(e), Included(i)) if i <= e => Excluded(e), - (Included(i), Excluded(e)) | (Excluded(e), Included(i)) if e < i => Included(i), - (s, Unbounded) | (Unbounded, s) => bound_as_ref(s), - _ => unreachable!(), - } - .cloned(); - let end = match (left_end, right_end) { - (Included(l), Included(r)) => Included(std::cmp::min(l, r)), - (Excluded(l), Excluded(r)) => Excluded(std::cmp::min(l, r)), - - (Included(i), Excluded(e)) | (Excluded(e), Included(i)) if i >= e => Excluded(e), - (Included(i), Excluded(e)) | (Excluded(e), Included(i)) if e > i => Included(i), - (s, Unbounded) | (Unbounded, s) => bound_as_ref(s), - _ => unreachable!(), - } - .cloned(); - left_iter.next_if(|(_, e)| e == &end); - right_iter.next_if(|(_, e)| e == &end); - if valid_segment(&start, &end) { - segments.push((start, end)) - } - } - - Self { segments }.check_invariants() - } -} - -impl VersionSet for Range { - type V = T; - - fn empty() -> Self { - Range::empty() - } - - fn singleton(v: Self::V) -> Self { - Range::singleton(v) - } - - fn complement(&self) -> Self { - Range::complement(self) - } - - fn intersection(&self, other: &Self) -> Self { - Range::intersection(self, other) - } - - fn contains(&self, v: &Self::V) -> bool { - Range::contains(self, v) - } - - fn full() -> Self { - Range::full() - } - - fn union(&self, other: &Self) -> Self { - Range::union(self, other) - } -} - -// REPORT ###################################################################### - -impl Display for Range { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { - if self.segments.is_empty() { - write!(f, "āˆ…")?; - } else { - for (idx, segment) in self.segments.iter().enumerate() { - if idx > 0 { - write!(f, ", ")?; - } - match segment { - (Unbounded, Unbounded) => write!(f, "*")?, - (Unbounded, Included(v)) => write!(f, "<={v}")?, - (Unbounded, Excluded(v)) => write!(f, "<{v}")?, - (Included(v), Unbounded) => write!(f, ">={v}")?, - (Included(v), Included(b)) => { - if v == b { - write!(f, "=={v}")? - } else { - write!(f, ">={v},<={b}")? - } - } - (Included(v), Excluded(b)) => write!(f, ">={v}, <{b}")?, - (Excluded(v), Unbounded) => write!(f, ">{v}")?, - (Excluded(v), Included(b)) => write!(f, ">{v}, <={b}")?, - (Excluded(v), Excluded(b)) => write!(f, ">{v}, <{b}")?, - }; - } - } - Ok(()) - } -} - -// SERIALIZATION ############################################################### - -#[cfg(feature = "serde")] -impl<'de, V: serde::Deserialize<'de>> serde::Deserialize<'de> for Range { - fn deserialize>(deserializer: D) -> Result { - // This enables conversion from the "old" discrete implementation of `Range` to the new - // bounded one. - // - // Serialization is always performed in the new format. - #[derive(serde::Deserialize)] - #[serde(untagged)] - enum EitherInterval { - B(Bound, Bound), - D(V, Option), - } - - let bounds: SmallVec> = serde::Deserialize::deserialize(deserializer)?; - - let mut segments = SmallVec::Empty; - for i in bounds { - match i { - EitherInterval::B(l, r) => segments.push((l, r)), - EitherInterval::D(l, Some(r)) => segments.push((Included(l), Excluded(r))), - EitherInterval::D(l, None) => segments.push((Included(l), Unbounded)), - } - } - - Ok(Range { segments }) - } -} - -// TESTS ####################################################################### - -#[cfg(test)] -pub mod tests { - use proptest::prelude::*; - - use super::*; - - /// Generate version sets from a random vector of deltas between bounds. - /// Each bound is randomly inclusive or exclusive. - pub fn strategy() -> impl Strategy> { - ( - any::(), - prop::collection::vec(any::<(u32, bool)>(), 1..10), - ) - .prop_map(|(start_unbounded, deltas)| { - let mut start = if start_unbounded { - Some(Unbounded) - } else { - None - }; - let mut largest: u32 = 0; - let mut last_bound_was_inclusive = false; - let mut segments = SmallVec::Empty; - for (delta, inclusive) in deltas { - // Add the offset to the current bound - largest = match largest.checked_add(delta) { - Some(s) => s, - None => { - // Skip this offset, if it would result in a too large bound. - continue; - } - }; - - let current_bound = if inclusive { - Included(largest) - } else { - Excluded(largest) - }; - - // If we already have a start bound, the next offset defines the complete range. - // If we don't have a start bound, we have to generate one. - if let Some(start_bound) = start.take() { - // If the delta from the start bound is 0, the only authorized configuration is - // Included(x), Included(x) - if delta == 0 && !(matches!(start_bound, Included(_)) && inclusive) { - start = Some(start_bound); - continue; - } - last_bound_was_inclusive = inclusive; - segments.push((start_bound, current_bound)); - } else { - // If the delta from the end bound of the last range is 0 and - // any of the last ending or current starting bound is inclusive, - // we skip the delta because they basically overlap. - if delta == 0 && (last_bound_was_inclusive || inclusive) { - continue; - } - start = Some(current_bound); - } - } - - // If we still have a start bound, but didn't have enough deltas to complete another - // segment, we add an unbounded upperbound. - if let Some(start_bound) = start { - segments.push((start_bound, Unbounded)); - } - - return Range { segments }.check_invariants(); - }) - } - - fn version_strat() -> impl Strategy { - any::() - } - - proptest! { - - // Testing negate ---------------------------------- - - #[test] - fn negate_is_different(range in strategy()) { - assert_ne!(range.complement(), range); - } - - #[test] - fn double_negate_is_identity(range in strategy()) { - assert_eq!(range.complement().complement(), range); - } - - #[test] - fn negate_contains_opposite(range in strategy(), version in version_strat()) { - assert_ne!(range.contains(&version), range.complement().contains(&version)); - } - - // Testing intersection ---------------------------- - - #[test] - fn intersection_is_symmetric(r1 in strategy(), r2 in strategy()) { - assert_eq!(r1.intersection(&r2), r2.intersection(&r1)); - } - - #[test] - fn intersection_with_any_is_identity(range in strategy()) { - assert_eq!(Range::full().intersection(&range), range); - } - - #[test] - fn intersection_with_none_is_none(range in strategy()) { - assert_eq!(Range::empty().intersection(&range), Range::empty()); - } - - #[test] - fn intersection_is_idempotent(r1 in strategy(), r2 in strategy()) { - assert_eq!(r1.intersection(&r2).intersection(&r2), r1.intersection(&r2)); - } - - #[test] - fn intersection_is_associative(r1 in strategy(), r2 in strategy(), r3 in strategy()) { - assert_eq!(r1.intersection(&r2).intersection(&r3), r1.intersection(&r2.intersection(&r3))); - } - - #[test] - fn intesection_of_complements_is_none(range in strategy()) { - assert_eq!(range.complement().intersection(&range), Range::empty()); - } - - #[test] - fn intesection_contains_both(r1 in strategy(), r2 in strategy(), version in version_strat()) { - assert_eq!(r1.intersection(&r2).contains(&version), r1.contains(&version) && r2.contains(&version)); - } - - // Testing union ----------------------------------- - - #[test] - fn union_of_complements_is_any(range in strategy()) { - assert_eq!(range.complement().union(&range), Range::full()); - } - - #[test] - fn union_contains_either(r1 in strategy(), r2 in strategy(), version in version_strat()) { - assert_eq!(r1.union(&r2).contains(&version), r1.contains(&version) || r2.contains(&version)); - } - - // Testing contains -------------------------------- - - #[test] - fn always_contains_exact(version in version_strat()) { - assert!(Range::singleton(version).contains(&version)); - } - - #[test] - fn contains_negation(range in strategy(), version in version_strat()) { - assert_ne!(range.contains(&version), range.complement().contains(&version)); - } - - #[test] - fn contains_intersection(range in strategy(), version in version_strat()) { - assert_eq!(range.contains(&version), range.intersection(&Range::singleton(version)) != Range::empty()); - } - - #[test] - fn contains_bounding_range(range in strategy(), version in version_strat()) { - if range.contains(&version) { - assert!(range.bounding_range().map(|b| b.contains(&version)).unwrap_or(false)); - } - } - - #[test] - fn from_range_bounds(range in any::<(Bound, Bound)>(), version in version_strat()) { - let rv: Range<_> = Range::from_range_bounds(range); - assert_eq!(range.contains(&version), rv.contains(&version)); - } - - #[test] - fn from_range_bounds_round_trip(range in any::<(Bound, Bound)>()) { - let rv: Range = Range::from_range_bounds(range); - let rv2: Range = rv.bounding_range().map(Range::from_range_bounds::<_, u32>).unwrap_or_else(Range::empty); - assert_eq!(rv, rv2); - } - } -} diff --git a/vendor/pubgrub/src/report.rs b/vendor/pubgrub/src/report.rs deleted file mode 100644 index ff0b2d3f0..000000000 --- a/vendor/pubgrub/src/report.rs +++ /dev/null @@ -1,481 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Build a report as clear as possible as to why -//! dependency solving failed. - -use std::fmt; -use std::ops::{Deref, DerefMut}; - -use crate::package::Package; -use crate::term::Term; -use crate::type_aliases::Map; -use crate::version_set::VersionSet; - -/// Reporter trait. -pub trait Reporter { - /// Output type of the report. - type Output; - - /// Generate a report from the derivation tree - /// describing the resolution failure. - fn report(derivation_tree: &DerivationTree) -> Self::Output; -} - -/// Derivation tree resulting in the impossibility -/// to solve the dependencies of our root package. -#[derive(Debug, Clone)] -pub enum DerivationTree { - /// External incompatibility. - External(External), - /// Incompatibility derived from two others. - Derived(Derived), -} - -/// Incompatibilities that are not derived from others, -/// they have their own reason. -#[derive(Debug, Clone)] -pub enum External { - /// Initial incompatibility aiming at picking the root package for the first decision. - NotRoot(P, VS::V), - /// There are no versions in the given set for this package. - NoVersions(P, VS), - /// Dependencies of the package are unavailable for versions in that set. - UnavailableDependencies(P, VS), - /// Incompatibility coming from the dependencies of a given package. - FromDependencyOf(P, VS, P, VS), -} - -/// Incompatibility derived from two others. -#[derive(Debug, Clone)] -pub struct Derived { - /// Terms of the incompatibility. - pub terms: Map>, - /// Indicate if that incompatibility is present multiple times - /// in the derivation tree. - /// If that is the case, it has a unique id, provided in that option. - /// Then, we may want to only explain it once, - /// and refer to the explanation for the other times. - pub shared_id: Option, - /// First cause. - pub cause1: Box>, - /// Second cause. - pub cause2: Box>, -} - -impl DerivationTree { - /// Merge the [NoVersions](External::NoVersions) external incompatibilities - /// with the other one they are matched with - /// in a derived incompatibility. - /// This cleans up quite nicely the generated report. - /// You might want to do this if you know that the - /// [DependencyProvider](crate::solver::DependencyProvider) - /// was not run in some kind of offline mode that may not - /// have access to all versions existing. - pub fn collapse_no_versions(&mut self) { - match self { - DerivationTree::External(_) => {} - DerivationTree::Derived(derived) => { - match (derived.cause1.deref_mut(), derived.cause2.deref_mut()) { - (DerivationTree::External(External::NoVersions(p, r)), ref mut cause2) => { - cause2.collapse_no_versions(); - *self = cause2 - .clone() - .merge_no_versions(p.to_owned(), r.to_owned()) - .unwrap_or_else(|| self.to_owned()); - } - (ref mut cause1, DerivationTree::External(External::NoVersions(p, r))) => { - cause1.collapse_no_versions(); - *self = cause1 - .clone() - .merge_no_versions(p.to_owned(), r.to_owned()) - .unwrap_or_else(|| self.to_owned()); - } - _ => { - derived.cause1.collapse_no_versions(); - derived.cause2.collapse_no_versions(); - } - } - } - } - } - - fn merge_no_versions(self, package: P, set: VS) -> Option { - match self { - // TODO: take care of the Derived case. - // Once done, we can remove the Option. - DerivationTree::Derived(_) => Some(self), - DerivationTree::External(External::NotRoot(_, _)) => { - panic!("How did we end up with a NoVersions merged with a NotRoot?") - } - DerivationTree::External(External::NoVersions(_, r)) => Some(DerivationTree::External( - External::NoVersions(package, set.union(&r)), - )), - DerivationTree::External(External::UnavailableDependencies(_, r)) => Some( - DerivationTree::External(External::UnavailableDependencies(package, set.union(&r))), - ), - DerivationTree::External(External::FromDependencyOf(p1, r1, p2, r2)) => { - if p1 == package { - Some(DerivationTree::External(External::FromDependencyOf( - p1, - r1.union(&set), - p2, - r2, - ))) - } else { - Some(DerivationTree::External(External::FromDependencyOf( - p1, - r1, - p2, - r2.union(&set), - ))) - } - } - } - } -} - -impl fmt::Display for External { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::NotRoot(package, version) => { - write!(f, "we are solving dependencies of {} {}", package, version) - } - Self::NoVersions(package, set) => { - if set == &VS::full() { - write!(f, "there is no available version for {}", package) - } else { - write!(f, "there is no version of {} in {}", package, set) - } - } - Self::UnavailableDependencies(package, set) => { - if set == &VS::full() { - write!(f, "dependencies of {} are unavailable", package) - } else { - write!( - f, - "dependencies of {} at version {} are unavailable", - package, set - ) - } - } - Self::FromDependencyOf(p, set_p, dep, set_dep) => { - if set_p == &VS::full() && set_dep == &VS::full() { - write!(f, "{} depends on {}", p, dep) - } else if set_p == &VS::full() { - write!(f, "{} depends on {} {}", p, dep, set_dep) - } else if set_dep == &VS::full() { - write!(f, "{} {} depends on {}", p, set_p, dep) - } else { - write!(f, "{} {} depends on {} {}", p, set_p, dep, set_dep) - } - } - } - } -} - -/// Default reporter able to generate an explanation as a [String]. -pub struct DefaultStringReporter { - /// Number of explanations already with a line reference. - ref_count: usize, - /// Shared nodes that have already been marked with a line reference. - /// The incompatibility ids are the keys, and the line references are the values. - shared_with_ref: Map, - /// Accumulated lines of the report already generated. - lines: Vec, -} - -impl DefaultStringReporter { - /// Initialize the reporter. - fn new() -> Self { - Self { - ref_count: 0, - shared_with_ref: Map::default(), - lines: Vec::new(), - } - } - - fn build_recursive(&mut self, derived: &Derived) { - self.build_recursive_helper(derived); - if let Some(id) = derived.shared_id { - if self.shared_with_ref.get(&id).is_none() { - self.add_line_ref(); - self.shared_with_ref.insert(id, self.ref_count); - } - }; - } - - fn build_recursive_helper(&mut self, current: &Derived) { - match (current.cause1.deref(), current.cause2.deref()) { - (DerivationTree::External(external1), DerivationTree::External(external2)) => { - // Simplest case, we just combine two external incompatibilities. - self.lines.push(Self::explain_both_external( - external1, - external2, - ¤t.terms, - )); - } - (DerivationTree::Derived(derived), DerivationTree::External(external)) => { - // One cause is derived, so we explain this first - // then we add the one-line external part - // and finally conclude with the current incompatibility. - self.report_one_each(derived, external, ¤t.terms); - } - (DerivationTree::External(external), DerivationTree::Derived(derived)) => { - self.report_one_each(derived, external, ¤t.terms); - } - (DerivationTree::Derived(derived1), DerivationTree::Derived(derived2)) => { - // This is the most complex case since both causes are also derived. - match ( - self.line_ref_of(derived1.shared_id), - self.line_ref_of(derived2.shared_id), - ) { - // If both causes already have been referenced (shared_id), - // the explanation simply uses those references. - (Some(ref1), Some(ref2)) => self.lines.push(Self::explain_both_ref( - ref1, - derived1, - ref2, - derived2, - ¤t.terms, - )), - // Otherwise, if one only has a line number reference, - // we recursively call the one without reference and then - // add the one with reference to conclude. - (Some(ref1), None) => { - self.build_recursive(derived2); - self.lines - .push(Self::and_explain_ref(ref1, derived1, ¤t.terms)); - } - (None, Some(ref2)) => { - self.build_recursive(derived1); - self.lines - .push(Self::and_explain_ref(ref2, derived2, ¤t.terms)); - } - // Finally, if no line reference exists yet, - // we call recursively the first one and then, - // - if this was a shared node, it will get a line ref - // and we can simply recall this with the current node. - // - otherwise, we add a line reference to it, - // recursively call on the second node, - // and finally conclude. - (None, None) => { - self.build_recursive(derived1); - if derived1.shared_id.is_some() { - self.lines.push("".into()); - self.build_recursive(current); - } else { - self.add_line_ref(); - let ref1 = self.ref_count; - self.lines.push("".into()); - self.build_recursive(derived2); - self.lines - .push(Self::and_explain_ref(ref1, derived1, ¤t.terms)); - } - } - } - } - } - } - - /// Report a derived and an external incompatibility. - /// - /// The result will depend on the fact that the derived incompatibility - /// has already been explained or not. - fn report_one_each( - &mut self, - derived: &Derived, - external: &External, - current_terms: &Map>, - ) { - match self.line_ref_of(derived.shared_id) { - Some(ref_id) => self.lines.push(Self::explain_ref_and_external( - ref_id, - derived, - external, - current_terms, - )), - None => self.report_recurse_one_each(derived, external, current_terms), - } - } - - /// Report one derived (without a line ref yet) and one external. - fn report_recurse_one_each( - &mut self, - derived: &Derived, - external: &External, - current_terms: &Map>, - ) { - match (derived.cause1.deref(), derived.cause2.deref()) { - // If the derived cause has itself one external prior cause, - // we can chain the external explanations. - (DerivationTree::Derived(prior_derived), DerivationTree::External(prior_external)) => { - self.build_recursive(prior_derived); - self.lines.push(Self::and_explain_prior_and_external( - prior_external, - external, - current_terms, - )); - } - // If the derived cause has itself one external prior cause, - // we can chain the external explanations. - (DerivationTree::External(prior_external), DerivationTree::Derived(prior_derived)) => { - self.build_recursive(prior_derived); - self.lines.push(Self::and_explain_prior_and_external( - prior_external, - external, - current_terms, - )); - } - _ => { - self.build_recursive(derived); - self.lines - .push(Self::and_explain_external(external, current_terms)); - } - } - } - - // String explanations ##################################################### - - /// Simplest case, we just combine two external incompatibilities. - fn explain_both_external( - external1: &External, - external2: &External, - current_terms: &Map>, - ) -> String { - // TODO: order should be chosen to make it more logical. - format!( - "Because {} and {}, {}.", - external1, - external2, - Self::string_terms(current_terms) - ) - } - - /// Both causes have already been explained so we use their refs. - fn explain_both_ref( - ref_id1: usize, - derived1: &Derived, - ref_id2: usize, - derived2: &Derived, - current_terms: &Map>, - ) -> String { - // TODO: order should be chosen to make it more logical. - format!( - "Because {} ({}) and {} ({}), {}.", - Self::string_terms(&derived1.terms), - ref_id1, - Self::string_terms(&derived2.terms), - ref_id2, - Self::string_terms(current_terms) - ) - } - - /// One cause is derived (already explained so one-line), - /// the other is a one-line external cause, - /// and finally we conclude with the current incompatibility. - fn explain_ref_and_external( - ref_id: usize, - derived: &Derived, - external: &External, - current_terms: &Map>, - ) -> String { - // TODO: order should be chosen to make it more logical. - format!( - "Because {} ({}) and {}, {}.", - Self::string_terms(&derived.terms), - ref_id, - external, - Self::string_terms(current_terms) - ) - } - - /// Add an external cause to the chain of explanations. - fn and_explain_external( - external: &External, - current_terms: &Map>, - ) -> String { - format!( - "And because {}, {}.", - external, - Self::string_terms(current_terms) - ) - } - - /// Add an already explained incompat to the chain of explanations. - fn and_explain_ref( - ref_id: usize, - derived: &Derived, - current_terms: &Map>, - ) -> String { - format!( - "And because {} ({}), {}.", - Self::string_terms(&derived.terms), - ref_id, - Self::string_terms(current_terms) - ) - } - - /// Add an already explained incompat to the chain of explanations. - fn and_explain_prior_and_external( - prior_external: &External, - external: &External, - current_terms: &Map>, - ) -> String { - format!( - "And because {} and {}, {}.", - prior_external, - external, - Self::string_terms(current_terms) - ) - } - - /// Try to print terms of an incompatibility in a human-readable way. - pub fn string_terms(terms: &Map>) -> String { - let terms_vec: Vec<_> = terms.iter().collect(); - match terms_vec.as_slice() { - [] => "version solving failed".into(), - // TODO: special case when that unique package is root. - [(package, Term::Positive(range))] => format!("{} {} is forbidden", package, range), - [(package, Term::Negative(range))] => format!("{} {} is mandatory", package, range), - [(p1, Term::Positive(r1)), (p2, Term::Negative(r2))] => { - External::FromDependencyOf(p1, r1.clone(), p2, r2.clone()).to_string() - } - [(p1, Term::Negative(r1)), (p2, Term::Positive(r2))] => { - External::FromDependencyOf(p2, r2.clone(), p1, r1.clone()).to_string() - } - slice => { - let str_terms: Vec<_> = slice.iter().map(|(p, t)| format!("{} {}", p, t)).collect(); - str_terms.join(", ") + " are incompatible" - } - } - } - - // Helper functions ######################################################## - - fn add_line_ref(&mut self) { - let new_count = self.ref_count + 1; - self.ref_count = new_count; - if let Some(line) = self.lines.last_mut() { - *line = format!("{} ({})", line, new_count); - } - } - - fn line_ref_of(&self, shared_id: Option) -> Option { - shared_id.and_then(|id| self.shared_with_ref.get(&id).cloned()) - } -} - -impl Reporter for DefaultStringReporter { - type Output = String; - - fn report(derivation_tree: &DerivationTree) -> Self::Output { - match derivation_tree { - DerivationTree::External(external) => external.to_string(), - DerivationTree::Derived(derived) => { - let mut reporter = Self::new(); - reporter.build_recursive(derived); - reporter.lines.join("\n") - } - } - } -} diff --git a/vendor/pubgrub/src/solver.rs b/vendor/pubgrub/src/solver.rs deleted file mode 100644 index 1728d1fe0..000000000 --- a/vendor/pubgrub/src/solver.rs +++ /dev/null @@ -1,374 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! PubGrub version solving algorithm. -//! -//! It consists in efficiently finding a set of packages and versions -//! that satisfy all the constraints of a given project dependencies. -//! In addition, when that is not possible, -//! PubGrub tries to provide a very human-readable and clear -//! explanation as to why that failed. -//! Below is an example of explanation present in -//! the introductory blog post about PubGrub -//! -//! ```txt -//! Because dropdown >=2.0.0 depends on icons >=2.0.0 and -//! root depends on icons <2.0.0, dropdown >=2.0.0 is forbidden. -//! -//! And because menu >=1.1.0 depends on dropdown >=2.0.0, -//! menu >=1.1.0 is forbidden. -//! -//! And because menu <1.1.0 depends on dropdown >=1.0.0 <2.0.0 -//! which depends on intl <4.0.0, every version of menu -//! requires intl <4.0.0. -//! -//! So, because root depends on both menu >=1.0.0 and intl >=5.0.0, -//! version solving failed. -//! ``` -//! -//! The algorithm is generic and works for any type of dependency system -//! as long as packages (P) and versions (V) implement -//! the [Package] and [Version](crate::version::Version) traits. -//! [Package] is strictly equivalent and automatically generated -//! for any type that implement [Clone] + [Eq] + [Hash] + [Debug] + [Display](std::fmt::Display). -//! [Version](crate::version::Version) simply states that versions are ordered, -//! that there should be -//! a minimal [lowest](crate::version::Version::lowest) version (like 0.0.0 in semantic versions), -//! and that for any version, it is possible to compute -//! what the next version closest to this one is ([bump](crate::version::Version::bump)). -//! For semantic versions, [bump](crate::version::Version::bump) corresponds to -//! an increment of the patch number. -//! -//! ## API -//! -//! ``` -//! # use pubgrub::solver::{resolve, OfflineDependencyProvider}; -//! # use pubgrub::version::NumberVersion; -//! # use pubgrub::error::PubGrubError; -//! # use pubgrub::range::Range; -//! # -//! # type NumVS = Range; -//! # -//! # fn try_main() -> Result<(), PubGrubError<&'static str, NumVS>> { -//! # let dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new(); -//! # let package = "root"; -//! # let version = 1; -//! let solution = resolve(&dependency_provider, package, version)?; -//! # Ok(()) -//! # } -//! # fn main() { -//! # assert!(matches!(try_main(), Err(PubGrubError::NoSolution(_)))); -//! # } -//! ``` -//! -//! Where `dependency_provider` supplies the list of available packages and versions, -//! as well as the dependencies of every available package -//! by implementing the [DependencyProvider] trait. -//! The call to [resolve] for a given package at a given version -//! will compute the set of packages and versions needed -//! to satisfy the dependencies of that package and version pair. -//! If there is no solution, the reason will be provided as clear as possible. - -use std::cmp::Reverse; -use std::collections::{BTreeMap, BTreeSet as Set}; -use std::error::Error; - -use crate::error::PubGrubError; -pub use crate::internal::core::State; -pub use crate::internal::incompatibility::{Incompatibility, Kind}; -use crate::package::Package; -use crate::type_aliases::{DependencyConstraints, Map, SelectedDependencies}; -use crate::version_set::VersionSet; -use log::{debug, info}; - -/// Main function of the library. -/// Finds a set of packages satisfying dependency bounds for a given package + version pair. -pub fn resolve( - dependency_provider: &impl DependencyProvider, - package: P, - version: impl Into, -) -> Result, PubGrubError> { - let mut state = State::init(package.clone(), version.into()); - let mut added_dependencies: Map> = Map::default(); - let mut next = package; - loop { - dependency_provider - .should_cancel() - .map_err(|err| PubGrubError::ErrorInShouldCancel(err))?; - - info!("unit_propagation: {}", &next); - state.unit_propagation(next)?; - - debug!( - "Partial solution after unit propagation: {}", - state.partial_solution - ); - - let Some(highest_priority_pkg) = state - .partial_solution - .pick_highest_priority_pkg(|p, r| dependency_provider.prioritize(p, r)) - else { - return Ok(state.partial_solution.extract_solution()); - }; - next = highest_priority_pkg; - - let term_intersection = state - .partial_solution - .term_intersection_for_package(&next) - .ok_or_else(|| { - PubGrubError::Failure("a package was chosen but we don't have a term.".into()) - })?; - let decision = dependency_provider - .choose_version(&next, term_intersection.unwrap_positive()) - .map_err(PubGrubError::ErrorChoosingPackageVersion)?; - info!("DP chose: {} @ {:?}", next, decision); - - // Pick the next compatible version. - let v = match decision { - None => { - let inc = Incompatibility::no_versions(next.clone(), term_intersection.clone()); - state.add_incompatibility(inc); - continue; - } - Some(x) => x, - }; - - if !term_intersection.contains(&v) { - return Err(PubGrubError::ErrorChoosingPackageVersion( - "choose_package_version picked an incompatible version".into(), - )); - } - - let is_new_dependency = added_dependencies - .entry(next.clone()) - .or_default() - .insert(v.clone()); - - if is_new_dependency { - // Retrieve that package dependencies. - let p = &next; - let dependencies = dependency_provider.get_dependencies(p, &v).map_err(|err| { - PubGrubError::ErrorRetrievingDependencies { - package: p.clone(), - version: v.clone(), - source: err, - } - })?; - - let known_dependencies = match dependencies { - Dependencies::Unknown => { - state.add_incompatibility(Incompatibility::unavailable_dependencies( - p.clone(), - v.clone(), - )); - continue; - } - Dependencies::Known(x) if x.contains_key(p) => { - return Err(PubGrubError::SelfDependency { - package: p.clone(), - version: v, - }); - } - Dependencies::Known(x) => x, - }; - - // Add that package and version if the dependencies are not problematic. - let dep_incompats = state.add_incompatibility_from_dependencies( - p.clone(), - v.clone(), - &known_dependencies, - ); - - state.partial_solution.add_version( - p.clone(), - v, - dep_incompats, - &state.incompatibility_store, - ); - } else { - // `dep_incompats` are already in `incompatibilities` so we know there are not satisfied - // terms and can add the decision directly. - info!("add_decision (not first time): {} @ {}", &next, v); - state.partial_solution.add_decision(next.clone(), v); - } - } -} - -/// An enum used by [DependencyProvider] that holds information about package dependencies. -/// For each [Package] there is a set of versions allowed as a dependency. -#[derive(Clone)] -pub enum Dependencies { - /// Package dependencies are unavailable. - Unknown, - /// Container for all available package versions. - Known(DependencyConstraints), -} - -/// Trait that allows the algorithm to retrieve available packages and their dependencies. -/// An implementor needs to be supplied to the [resolve] function. -pub trait DependencyProvider { - /// [Decision making](https://github.com/dart-lang/pub/blob/master/doc/solver.md#decision-making) - /// is the process of choosing the next package - /// and version that will be appended to the partial solution. - /// - /// Every time such a decision must be made, the resolver looks at all the potential valid - /// packages that have changed, and a asks the dependency provider how important each one is. - /// For each one it calls `prioritize` with the name of the package and the current set of - /// acceptable versions. - /// The resolver will then pick the package with the highes priority from all the potential valid - /// packages. - /// - /// The strategy employed to prioritize packages - /// cannot change the existence of a solution or not, - /// but can drastically change the performances of the solver, - /// or the properties of the solution. - /// The documentation of Pub (PubGrub implementation for the dart programming language) - /// states the following: - /// - /// > Pub chooses the latest matching version of the package - /// > with the fewest versions that match the outstanding constraint. - /// > This tends to find conflicts earlier if any exist, - /// > since these packages will run out of versions to try more quickly. - /// > But there's likely room for improvement in these heuristics. - /// - /// Note: the resolver may call this even when the range has not change, - /// if it is more efficient for the resolveres internal data structures. - fn prioritize(&self, package: &P, range: &VS) -> Self::Priority; - /// The type returned from `prioritize`. The resolver does not care what type this is - /// as long as it can pick a largest one and clone it. - /// - /// [std::cmp::Reverse] can be useful if you want to pick the package with - /// the fewest versions that match the outstanding constraint. - type Priority: Ord + Clone; - - /// Once the resolver has found the highest `Priority` package from all potential valid - /// packages, it needs to know what vertion of that package to use. The most common pattern - /// is to select the largest vertion that the range contains. - fn choose_version( - &self, - package: &P, - range: &VS, - ) -> Result, Box>; - - /// Retrieves the package dependencies. - /// Return [Dependencies::Unknown] if its dependencies are unknown. - fn get_dependencies( - &self, - package: &P, - version: &VS::V, - ) -> Result, Box>; - - /// This is called fairly regularly during the resolution, - /// if it returns an Err then resolution will be terminated. - /// This is helpful if you want to add some form of early termination like a timeout, - /// or you want to add some form of user feedback if things are taking a while. - /// If not provided the resolver will run as long as needed. - fn should_cancel(&self) -> Result<(), Box> { - Ok(()) - } -} - -/// A basic implementation of [DependencyProvider]. -#[derive(Debug, Clone, Default)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr( - feature = "serde", - serde(bound( - serialize = "VS::V: serde::Serialize, VS: serde::Serialize, P: serde::Serialize", - deserialize = "VS::V: serde::Deserialize<'de>, VS: serde::Deserialize<'de>, P: serde::Deserialize<'de>" - )) -)] -#[cfg_attr(feature = "serde", serde(transparent))] -pub struct OfflineDependencyProvider { - dependencies: Map>>, -} - -impl OfflineDependencyProvider { - /// Creates an empty OfflineDependencyProvider with no dependencies. - pub fn new() -> Self { - Self { - dependencies: Map::default(), - } - } - - /// Registers the dependencies of a package and version pair. - /// Dependencies must be added with a single call to - /// [add_dependencies](OfflineDependencyProvider::add_dependencies). - /// All subsequent calls to - /// [add_dependencies](OfflineDependencyProvider::add_dependencies) for a given - /// package version pair will replace the dependencies by the new ones. - /// - /// The API does not allow to add dependencies one at a time to uphold an assumption that - /// [OfflineDependencyProvider.get_dependencies(p, v)](OfflineDependencyProvider::get_dependencies) - /// provides all dependencies of a given package (p) and version (v) pair. - pub fn add_dependencies>( - &mut self, - package: P, - version: impl Into, - dependencies: I, - ) { - let package_deps = dependencies.into_iter().collect(); - let v = version.into(); - *self - .dependencies - .entry(package) - .or_default() - .entry(v) - .or_default() = package_deps; - } - - /// Lists packages that have been saved. - pub fn packages(&self) -> impl Iterator { - self.dependencies.keys() - } - - /// Lists versions of saved packages in sorted order. - /// Returns [None] if no information is available regarding that package. - pub fn versions(&self, package: &P) -> Option> { - self.dependencies.get(package).map(|k| k.keys()) - } - - /// Lists dependencies of a given package and version. - /// Returns [None] if no information is available regarding that package and version pair. - fn dependencies(&self, package: &P, version: &VS::V) -> Option> { - self.dependencies.get(package)?.get(version).cloned() - } -} - -/// An implementation of [DependencyProvider] that -/// contains all dependency information available in memory. -/// Currently packages are picked with the fewest versions contained in the constraints first. -/// But, that may change in new versions if better heuristics are found. -/// Versions are picked with the newest versions first. -impl DependencyProvider for OfflineDependencyProvider { - fn choose_version( - &self, - package: &P, - range: &VS, - ) -> Result, Box> { - Ok(self - .dependencies - .get(package) - .and_then(|versions| versions.keys().rev().find(|v| range.contains(v)).cloned())) - } - - type Priority = Reverse; - fn prioritize(&self, package: &P, range: &VS) -> Self::Priority { - Reverse( - self.dependencies - .get(package) - .map(|versions| versions.keys().filter(|v| range.contains(v)).count()) - .unwrap_or(0), - ) - } - - fn get_dependencies( - &self, - package: &P, - version: &VS::V, - ) -> Result, Box> { - Ok(match self.dependencies(package, version) { - None => Dependencies::Unknown, - Some(dependencies) => Dependencies::Known(dependencies), - }) - } -} diff --git a/vendor/pubgrub/src/term.rs b/vendor/pubgrub/src/term.rs deleted file mode 100644 index 895afdfe0..000000000 --- a/vendor/pubgrub/src/term.rs +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! A term is the fundamental unit of operation of the PubGrub algorithm. -//! It is a positive or negative expression regarding a set of versions. - -use crate::version_set::VersionSet; -use std::fmt::{self, Display}; - -/// A positive or negative expression regarding a set of versions. -#[derive(Debug, Clone, Eq, PartialEq)] -pub enum Term { - /// For example, "1.0.0 <= v < 2.0.0" is a positive expression - /// that is evaluated true if a version is selected - /// and comprised between version 1.0.0 and version 2.0.0. - Positive(VS), - /// The term "not v < 3.0.0" is a negative expression - /// that is evaluated true if a version is selected >= 3.0.0 - /// or if no version is selected at all. - Negative(VS), -} - -/// Base methods. -impl Term { - /// A term that is always true. - pub(crate) fn any() -> Self { - Self::Negative(VS::empty()) - } - - /// A term that is never true. - pub(crate) fn empty() -> Self { - Self::Positive(VS::empty()) - } - - /// A positive term containing exactly that version. - pub(crate) fn exact(version: VS::V) -> Self { - Self::Positive(VS::singleton(version)) - } - - /// Simply check if a term is positive. - pub(crate) fn is_positive(&self) -> bool { - match self { - Self::Positive(_) => true, - Self::Negative(_) => false, - } - } - - /// Negate a term. - /// Evaluation of a negated term always returns - /// the opposite of the evaluation of the original one. - pub(crate) fn negate(&self) -> Self { - match self { - Self::Positive(set) => Self::Negative(set.clone()), - Self::Negative(set) => Self::Positive(set.clone()), - } - } - - /// Evaluate a term regarding a given choice of version. - pub(crate) fn contains(&self, v: &VS::V) -> bool { - match self { - Self::Positive(set) => set.contains(v), - Self::Negative(set) => !(set.contains(v)), - } - } - - /// Unwrap the set contained in a positive term. - /// Will panic if used on a negative set. - pub fn unwrap_positive(&self) -> &VS { - match self { - Self::Positive(set) => set, - _ => panic!("Negative term cannot unwrap positive set"), - } - } -} - -/// Set operations with terms. -impl Term { - /// Compute the intersection of two terms. - /// If at least one term is positive, the intersection is also positive. - pub(crate) fn intersection(&self, other: &Self) -> Self { - match (self, other) { - (Self::Positive(r1), Self::Positive(r2)) => Self::Positive(r1.intersection(r2)), - (Self::Positive(r1), Self::Negative(r2)) => { - Self::Positive(r1.intersection(&r2.complement())) - } - (Self::Negative(r1), Self::Positive(r2)) => { - Self::Positive(r1.complement().intersection(r2)) - } - (Self::Negative(r1), Self::Negative(r2)) => Self::Negative(r1.union(r2)), - } - } - - /// Compute the union of two terms. - /// If at least one term is negative, the union is also negative. - pub(crate) fn union(&self, other: &Self) -> Self { - (self.negate().intersection(&other.negate())).negate() - } - - /// Indicate if this term is a subset of another term. - /// Just like for sets, we say that t1 is a subset of t2 - /// if and only if t1 ∩ t2 = t1. - pub(crate) fn subset_of(&self, other: &Self) -> bool { - self == &self.intersection(other) - } -} - -/// Describe a relation between a set of terms S and another term t. -/// -/// As a shorthand, we say that a term v -/// satisfies or contradicts a term t if {v} satisfies or contradicts it. -pub(crate) enum Relation { - /// We say that a set of terms S "satisfies" a term t - /// if t must be true whenever every term in S is true. - Satisfied, - /// Conversely, S "contradicts" t if t must be false - /// whenever every term in S is true. - Contradicted, - /// If neither of these is true we say that S is "inconclusive" for t. - Inconclusive, -} - -/// Relation between terms. -impl Term { - /// Check if a set of terms satisfies this term. - /// - /// We say that a set of terms S "satisfies" a term t - /// if t must be true whenever every term in S is true. - /// - /// It turns out that this can also be expressed with set operations: - /// S satisfies t if and only if ā‹‚ S āŠ† t - #[cfg(test)] - fn satisfied_by(&self, terms_intersection: &Self) -> bool { - terms_intersection.subset_of(self) - } - - /// Check if a set of terms contradicts this term. - /// - /// We say that a set of terms S "contradicts" a term t - /// if t must be false whenever every term in S is true. - /// - /// It turns out that this can also be expressed with set operations: - /// S contradicts t if and only if ā‹‚ S is disjoint with t - /// S contradicts t if and only if (ā‹‚ S) ā‹‚ t = āˆ… - #[cfg(test)] - fn contradicted_by(&self, terms_intersection: &Self) -> bool { - terms_intersection.intersection(self) == Self::empty() - } - - /// Check if a set of terms satisfies or contradicts a given term. - /// Otherwise the relation is inconclusive. - pub(crate) fn relation_with(&self, other_terms_intersection: &Self) -> Relation { - let full_intersection = self.intersection(other_terms_intersection); - if &full_intersection == other_terms_intersection { - Relation::Satisfied - } else if full_intersection == Self::empty() { - Relation::Contradicted - } else { - Relation::Inconclusive - } - } -} - -impl AsRef for Term { - fn as_ref(&self) -> &Self { - self - } -} - -// REPORT ###################################################################### - -impl Display for Term { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Positive(set) => write!(f, "{}", set), - Self::Negative(set) => write!(f, "Not ( {} )", set), - } - } -} - -// TESTS ####################################################################### - -#[cfg(test)] -pub mod tests { - use super::*; - use crate::range::Range; - use proptest::prelude::*; - - pub fn strategy() -> impl Strategy>> { - prop_oneof![ - crate::range::tests::strategy().prop_map(Term::Positive), - crate::range::tests::strategy().prop_map(Term::Negative), - ] - } - - proptest! { - - // Testing relation -------------------------------- - - #[test] - fn relation_with(term1 in strategy(), term2 in strategy()) { - match term1.relation_with(&term2) { - Relation::Satisfied => assert!(term1.satisfied_by(&term2)), - Relation::Contradicted => assert!(term1.contradicted_by(&term2)), - Relation::Inconclusive => { - assert!(!term1.satisfied_by(&term2)); - assert!(!term1.contradicted_by(&term2)); - } - } - } - - } -} diff --git a/vendor/pubgrub/src/type_aliases.rs b/vendor/pubgrub/src/type_aliases.rs deleted file mode 100644 index 11cc37c75..000000000 --- a/vendor/pubgrub/src/type_aliases.rs +++ /dev/null @@ -1,17 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Publicly exported type aliases. - -/// Map implementation used by the library. -pub type Map = rustc_hash::FxHashMap; - -/// Concrete dependencies picked by the library during [resolve](crate::solver::resolve) -/// from [DependencyConstraints]. -pub type SelectedDependencies = Map; - -/// Holds information about all possible versions a given package can accept. -/// There is a difference in semantics between an empty map -/// inside [DependencyConstraints] and [Dependencies::Unknown](crate::solver::Dependencies::Unknown): -/// the former means the package has no dependency and it is a known fact, -/// while the latter means they could not be fetched by the [DependencyProvider](crate::solver::DependencyProvider). -pub type DependencyConstraints = Map; diff --git a/vendor/pubgrub/src/version.rs b/vendor/pubgrub/src/version.rs deleted file mode 100644 index 6f67c7dee..000000000 --- a/vendor/pubgrub/src/version.rs +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! Traits and implementations to create and compare versions. - -use std::fmt::{self, Debug, Display}; -use std::str::FromStr; -use thiserror::Error; - -/// Versions 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; -} - -/// Type for semantic versions: major.minor.patch. -#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] -pub struct SemanticVersion { - major: u32, - minor: u32, - patch: u32, -} - -#[cfg(feature = "serde")] -impl serde::Serialize for SemanticVersion { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - serializer.serialize_str(&format!("{}", self)) - } -} - -#[cfg(feature = "serde")] -impl<'de> serde::Deserialize<'de> for SemanticVersion { - fn deserialize(deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - FromStr::from_str(&s).map_err(serde::de::Error::custom) - } -} - -// Constructors -impl SemanticVersion { - /// Create a version with "major", "minor" and "patch" values. - /// `version = major.minor.patch` - pub fn new(major: u32, minor: u32, patch: u32) -> Self { - Self { - major, - minor, - patch, - } - } - - /// Version 0.0.0. - pub fn zero() -> Self { - Self::new(0, 0, 0) - } - - /// Version 1.0.0. - pub fn one() -> Self { - Self::new(1, 0, 0) - } - - /// Version 2.0.0. - pub fn two() -> Self { - Self::new(2, 0, 0) - } -} - -// Convert a tuple (major, minor, patch) into a version. -impl From<(u32, u32, u32)> for SemanticVersion { - fn from(tuple: (u32, u32, u32)) -> Self { - let (major, minor, patch) = tuple; - Self::new(major, minor, patch) - } -} - -// Convert a &(major, minor, patch) into a version. -impl From<&(u32, u32, u32)> for SemanticVersion { - fn from(tuple: &(u32, u32, u32)) -> Self { - let (major, minor, patch) = *tuple; - Self::new(major, minor, patch) - } -} - -// Convert an &version into a version. -impl From<&SemanticVersion> for SemanticVersion { - fn from(v: &SemanticVersion) -> Self { - *v - } -} - -// Convert a version into a tuple (major, minor, patch). -impl From for (u32, u32, u32) { - fn from(v: SemanticVersion) -> Self { - (v.major, v.minor, v.patch) - } -} - -// Bump versions. -impl SemanticVersion { - /// Bump the patch number of a version. - pub fn bump_patch(self) -> Self { - Self::new(self.major, self.minor, self.patch + 1) - } - - /// Bump the minor number of a version. - pub fn bump_minor(self) -> Self { - Self::new(self.major, self.minor + 1, 0) - } - - /// Bump the major number of a version. - pub fn bump_major(self) -> Self { - Self::new(self.major + 1, 0, 0) - } -} - -/// Error creating [SemanticVersion] from [String]. -#[derive(Error, Debug, PartialEq, Eq)] -pub enum VersionParseError { - /// [SemanticVersion] must contain major, minor, patch versions. - #[error("version {full_version} must contain 3 numbers separated by dot")] - NotThreeParts { - /// [SemanticVersion] that was being parsed. - full_version: String, - }, - /// Wrapper around [ParseIntError](core::num::ParseIntError). - #[error("cannot parse '{version_part}' in '{full_version}' as u32: {parse_error}")] - ParseIntError { - /// [SemanticVersion] that was being parsed. - full_version: String, - /// A version part where parsing failed. - version_part: String, - /// A specific error resulted from parsing a part of the version as [u32]. - parse_error: String, - }, -} - -impl FromStr for SemanticVersion { - type Err = VersionParseError; - - fn from_str(s: &str) -> Result { - let parse_u32 = |part: &str| { - part.parse::().map_err(|e| Self::Err::ParseIntError { - full_version: s.to_string(), - version_part: part.to_string(), - parse_error: e.to_string(), - }) - }; - - let mut parts = s.split('.'); - match (parts.next(), parts.next(), parts.next(), parts.next()) { - (Some(major), Some(minor), Some(patch), None) => { - let major = parse_u32(major)?; - let minor = parse_u32(minor)?; - let patch = parse_u32(patch)?; - Ok(Self { - major, - minor, - patch, - }) - } - _ => Err(Self::Err::NotThreeParts { - full_version: s.to_string(), - }), - } - } -} - -#[test] -fn from_str_for_semantic_version() { - let parse = |str: &str| str.parse::(); - assert!(parse( - &SemanticVersion { - major: 0, - minor: 1, - patch: 0 - } - .to_string() - ) - .is_ok()); - assert!(parse("1.2.3").is_ok()); - assert_eq!( - parse("1.abc.3"), - Err(VersionParseError::ParseIntError { - full_version: "1.abc.3".to_owned(), - version_part: "abc".to_owned(), - parse_error: "invalid digit found in string".to_owned(), - }) - ); - assert_eq!( - parse("1.2.-3"), - Err(VersionParseError::ParseIntError { - full_version: "1.2.-3".to_owned(), - version_part: "-3".to_owned(), - parse_error: "invalid digit found in string".to_owned(), - }) - ); - assert_eq!( - parse("1.2.9876543210"), - Err(VersionParseError::ParseIntError { - full_version: "1.2.9876543210".to_owned(), - version_part: "9876543210".to_owned(), - parse_error: "number too large to fit in target type".to_owned(), - }) - ); - assert_eq!( - parse("1.2"), - Err(VersionParseError::NotThreeParts { - full_version: "1.2".to_owned(), - }) - ); - assert_eq!( - parse("1.2.3."), - Err(VersionParseError::NotThreeParts { - full_version: "1.2.3.".to_owned(), - }) - ); -} - -impl Display for SemanticVersion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}.{}.{}", self.major, self.minor, self.patch) - } -} - -// Implement Version for SemanticVersion. -impl Version for SemanticVersion { - fn lowest() -> Self { - Self::zero() - } - fn bump(&self) -> Self { - self.bump_patch() - } -} - -/// Simplest versions possible, just a positive number. -#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize,))] -#[cfg_attr(feature = "serde", serde(transparent))] -pub struct NumberVersion(pub u32); - -// Convert an usize into a version. -impl From for NumberVersion { - fn from(v: u32) -> Self { - Self(v) - } -} - -// Convert an &usize into a version. -impl From<&u32> for NumberVersion { - fn from(v: &u32) -> Self { - Self(*v) - } -} - -// Convert an &version into a version. -impl From<&NumberVersion> for NumberVersion { - fn from(v: &NumberVersion) -> Self { - *v - } -} - -// Convert a version into an usize. -impl From for u32 { - fn from(version: NumberVersion) -> Self { - version.0 - } -} - -impl Display for NumberVersion { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "{}", self.0) - } -} - -impl Version for NumberVersion { - fn lowest() -> Self { - Self(0) - } - fn bump(&self) -> Self { - Self(self.0 + 1) - } -} diff --git a/vendor/pubgrub/src/version_set.rs b/vendor/pubgrub/src/version_set.rs deleted file mode 100644 index 501ec700a..000000000 --- a/vendor/pubgrub/src/version_set.rs +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -//! As its name suggests, the [VersionSet] trait describes sets of versions. -//! -//! One needs to define -//! - the associate type for versions, -//! - two constructors for the empty set and a singleton set, -//! - the complement and intersection set operations, -//! - and a function to evaluate membership of versions. -//! -//! Two functions are automatically derived, thanks to the mathematical properties of sets. -//! You can overwrite those implementations, but we highly recommend that you don't, -//! except if you are confident in a correct implementation that brings much performance gains. -//! -//! It is also extremely important that the `Eq` trait is correctly implemented. -//! In particular, you can only use `#[derive(Eq, PartialEq)]` if `Eq` is strictly equivalent to the -//! structural equality, i.e. if version sets have canonical representations. -//! Such problems may arise if your implementations of `complement()` and `intersection()` do not -//! return canonical representations so be careful there. - -use std::fmt::{Debug, Display}; - -/// 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. - /// Automatically implemented as `Self::empty().complement()`. - fn full() -> Self { - Self::empty().complement() - } - - /// Compute the union with another set. - /// Thanks to set properties, this is automatically implemented as: - /// `self.complement().intersection(&other.complement()).complement()` - fn union(&self, other: &Self) -> Self { - self.complement() - .intersection(&other.complement()) - .complement() - } -} diff --git a/vendor/pubgrub/test-examples/large_case_u16_NumberVersion.ron b/vendor/pubgrub/test-examples/large_case_u16_NumberVersion.ron deleted file mode 100644 index de52b769a..000000000 --- a/vendor/pubgrub/test-examples/large_case_u16_NumberVersion.ron +++ /dev/null @@ -1,5524 +0,0 @@ -{ - 0: { - 0: { - 13: [ - (10, Some(13)), - ], - 96: [ - (10, Some(15)), - ], - 344: [ - (0, Some(15)), - ], - 475: [ - (3, Some(4)), - ], - 479: [ - (0, None), - ], - 523: [ - (0, Some(10)), - ], - 600: [ - (0, None), - ], - }, - }, - 13: { - 10: { - 215: [ - (11, Some(14)), - ], - 227: [ - (10, None), - ], - 505: [ - (10, Some(14)), - ], - }, - 12: { - 100: [ - (6, None), - ], - 124: [ - (0, Some(15)), - ], - 208: [ - (0, Some(8)), - ], - 287: [ - (3, Some(6)), - ], - 396: [ - (9, Some(12)), - ], - 405: [ - (2, None), - ], - 574: [ - (0, Some(10)), - ], - }, - 13: { - 171: [ - (2, Some(12)), - ], - 441: [ - (0, Some(3)), - ], - 505: [ - (1, Some(18)), - ], - 547: [ - (18, None), - ], - }, - }, - 96: { - 10: { - 169: [ - (9, Some(11)), - ], - 259: [ - (0, Some(1)), - ], - 341: [ - (2, Some(15)), - ], - 344: [ - (13, Some(14)), - ], - 418: [ - (8, Some(16)), - ], - 443: [ - (0, Some(15)), - ], - 447: [ - (13, None), - ], - 500: [ - (5, Some(13)), - ], - 619: [ - (4, Some(15)), - ], - }, - 12: { - 128: [ - (5, Some(14)), - ], - 249: [ - (0, None), - ], - 352: [ - (10, Some(17)), - ], - 405: [ - (6, Some(12)), - ], - 595: [ - (15, None), - ], - 600: [ - (8, Some(10)), - ], - 613: [ - (0, Some(11)), - ], - }, - 14: { - 171: [ - (0, Some(3)), - ], - 242: [ - (5, Some(14)), - ], - 255: [ - (8, None), - ], - 370: [ - (16, None), - ], - 559: [ - (0, Some(9)), - ], - 574: [ - (0, Some(2)), - ], - 593: [ - (13, None), - ], - 599: [ - (10, Some(15)), - ], - }, - }, - 128: { - 5: { - 541: [ - (0, Some(14)), - ], - }, - 8: { - 316: [ - (13, Some(18)), - ], - 349: [ - (0, Some(11)), - ], - 410: [ - (5, Some(6)), - ], - 523: [ - (8, Some(11)), - ], - 547: [ - (13, Some(18)), - ], - 595: [ - (16, None), - ], - 619: [ - (2, None), - ], - }, - 9: { - 250: [ - (17, Some(19)), - ], - 259: [ - (10, None), - ], - 265: [ - (0, Some(8)), - ], - 287: [ - (12, Some(13)), - ], - 447: [ - (0, None), - ], - 455: [ - (12, Some(16)), - ], - 505: [ - (1, Some(18)), - ], - 541: [ - (0, Some(7)), - ], - 574: [ - (10, Some(15)), - ], - }, - 11: { - 190: [ - (0, Some(1)), - ], - 242: [ - (5, Some(10)), - ], - 265: [ - (11, Some(13)), - ], - 287: [ - (1, Some(3)), - ], - 316: [ - (14, None), - ], - 335: [ - (2, Some(4)), - ], - 344: [ - (6, None), - ], - 349: [ - (4, Some(15)), - ], - 418: [ - (3, Some(4)), - ], - 477: [ - (0, None), - ], - 595: [ - (16, Some(17)), - ], - 606: [ - (16, None), - ], - 635: [ - (0, Some(18)), - ], - }, - 12: { - 190: [ - (3, Some(14)), - ], - 250: [ - (5, Some(8)), - ], - 328: [ - (0, Some(16)), - ], - 484: [ - (6, Some(8)), - ], - 500: [ - (0, Some(3)), - ], - 547: [ - (14, Some(17)), - ], - }, - 13: { - 190: [ - (3, Some(6)), - ], - 312: [ - (10, Some(11)), - ], - 341: [ - (0, Some(7)), - ], - 348: [ - (10, None), - ], - 484: [ - (4, Some(9)), - ], - 495: [ - (5, Some(12)), - ], - }, - 15: { - 205: [ - (5, Some(13)), - ], - 312: [ - (10, Some(13)), - ], - 335: [ - (2, Some(7)), - ], - 346: [ - (10, None), - ], - 385: [ - (0, Some(4)), - ], - 589: [ - (0, Some(9)), - ], - }, - }, - 190: { - 0: { - 202: [ - (9, Some(10)), - ], - 251: [ - (0, Some(18)), - ], - 265: [ - (18, None), - ], - 293: [ - (7, Some(12)), - ], - 328: [ - (12, Some(13)), - ], - 535: [ - (13, Some(14)), - ], - }, - 3: { - 400: [ - (0, Some(1)), - ], - 441: [ - (0, None), - ], - }, - 5: { - 250: [ - (14, Some(19)), - ], - 619: [ - (4, Some(7)), - ], - 627: [ - (14, None), - ], - }, - 8: { - 265: [ - (0, Some(8)), - ], - 541: [ - (0, Some(7)), - ], - 560: [ - (0, Some(5)), - ], - 600: [ - (6, None), - ], - }, - 9: { - 199: [ - (3, Some(16)), - ], - 208: [ - (0, None), - ], - 227: [ - (4, Some(16)), - ], - 287: [ - (1, Some(12)), - ], - 334: [ - (0, Some(6)), - ], - 341: [ - (10, Some(12)), - ], - 348: [ - (7, None), - ], - 396: [ - (4, Some(19)), - ], - 400: [ - (4, Some(5)), - ], - 523: [ - (8, Some(9)), - ], - 547: [ - (2, Some(17)), - ], - }, - 11: { - 210: [ - (8, Some(15)), - ], - 334: [ - (5, Some(6)), - ], - 345: [ - (11, Some(12)), - ], - 349: [ - (3, None), - ], - 370: [ - (0, None), - ], - 484: [ - (0, Some(8)), - ], - 495: [ - (11, Some(13)), - ], - 594: [ - (11, None), - ], - }, - 12: { - 645: [ - (6, Some(17)), - ], - }, - 13: { - 205: [ - (2, Some(13)), - ], - 287: [ - (14, None), - ], - 328: [ - (12, Some(14)), - ], - 450: [ - (3, Some(17)), - ], - 491: [ - (2, Some(4)), - ], - 660: [ - (0, Some(4)), - ], - }, - 17: { - 245: [ - (2, Some(4)), - ], - 250: [ - (10, Some(12)), - ], - 364: [ - (9, None), - ], - 559: [ - (0, Some(13)), - ], - 576: [ - (7, Some(9)), - ], - }, - 19: { - 316: [ - (3, Some(17)), - ], - 589: [ - (7, None), - ], - 600: [ - (6, Some(9)), - ], - 608: [ - (6, Some(7)), - ], - 627: [ - (14, Some(15)), - ], - 662: [ - (8, Some(17)), - ], - }, - }, - 215: { - 8: { - 245: [ - (0, Some(2)), - ], - 334: [ - (0, Some(6)), - ], - 341: [ - (0, Some(12)), - ], - 450: [ - (0, Some(18)), - ], - 606: [ - (0, None), - ], - 608: [ - (0, Some(10)), - ], - }, - 11: { - 228: [ - (0, Some(15)), - ], - 245: [ - (0, Some(4)), - ], - 316: [ - (3, Some(18)), - ], - 505: [ - (1, Some(14)), - ], - 559: [ - (11, Some(13)), - ], - 601: [ - (8, Some(13)), - ], - 613: [ - (8, Some(11)), - ], - }, - 13: { - 450: [ - (3, Some(5)), - ], - 662: [ - (16, Some(19)), - ], - }, - 15: { - 349: [ - (10, Some(12)), - ], - 619: [ - (0, Some(7)), - ], - }, - }, - 227: { - 3: { - 348: [ - (0, Some(3)), - ], - 448: [ - (12, Some(13)), - ], - 559: [ - (9, Some(11)), - ], - 594: [ - (1, Some(12)), - ], - 650: [ - (0, Some(15)), - ], - }, - 4: { - 264: [ - (0, Some(4)), - ], - 344: [ - (6, Some(7)), - ], - 479: [ - (0, None), - ], - 562: [ - (4, Some(5)), - ], - }, - 5: { - 265: [ - (7, Some(10)), - ], - 316: [ - (14, Some(17)), - ], - 405: [ - (2, Some(8)), - ], - 471: [ - (0, None), - ], - 593: [ - (4, None), - ], - }, - 6: { - 448: [ - (0, Some(13)), - ], - 625: [ - (0, Some(7)), - ], - }, - 8: { - 328: [ - (13, Some(16)), - ], - 462: [ - (7, Some(8)), - ], - 495: [ - (0, Some(5)), - ], - 613: [ - (0, Some(4)), - ], - 627: [ - (0, Some(2)), - ], - 660: [ - (0, Some(10)), - ], - }, - 9: { - 334: [ - (11, None), - ], - 351: [ - (0, Some(7)), - ], - 410: [ - (5, Some(8)), - ], - 574: [ - (2, Some(15)), - ], - 599: [ - (2, Some(13)), - ], - }, - 10: { - 230: [ - (7, Some(17)), - ], - 242: [ - (4, None), - ], - 287: [ - (1, Some(7)), - ], - 650: [ - (14, None), - ], - }, - 14: { - 455: [ - (9, Some(18)), - ], - 625: [ - (8, Some(9)), - ], - }, - 15: { - 450: [ - (0, Some(4)), - ], - 523: [ - (11, Some(14)), - ], - }, - 16: { - 255: [ - (11, Some(14)), - ], - 589: [ - (1, None), - ], - }, - 17: { - 312: [ - (6, Some(12)), - ], - 348: [ - (9, Some(15)), - ], - 371: [ - (12, Some(19)), - ], - 455: [ - (4, Some(13)), - ], - 495: [ - (3, Some(9)), - ], - 547: [ - (6, None), - ], - 562: [ - (4, Some(13)), - ], - }, - 18: { - 312: [ - (15, None), - ], - 584: [ - (3, None), - ], - 660: [ - (0, None), - ], - }, - }, - 228: { - 6: { - 293: [ - (7, Some(11)), - ], - 341: [ - (0, Some(2)), - ], - 559: [ - (8, None), - ], - 608: [ - (6, None), - ], - 613: [ - (8, Some(11)), - ], - }, - 7: { - 523: [ - (9, None), - ], - 595: [ - (10, Some(15)), - ], - 662: [ - (16, Some(17)), - ], - }, - 14: { - 371: [ - (0, Some(12)), - ], - 491: [ - (0, None), - ], - }, - 15: { - 250: [ - (4, Some(18)), - ], - 265: [ - (0, Some(13)), - ], - 606: [ - (7, Some(17)), - ], - }, - 17: { - 341: [ - (0, Some(15)), - ], - 535: [ - (12, Some(13)), - ], - 559: [ - (11, None), - ], - }, - }, - 245: { - 1: { - 334: [ - (5, Some(9)), - ], - 613: [ - (0, Some(9)), - ], - }, - 2: { - 268: [ - (9, Some(14)), - ], - 541: [ - (7, Some(16)), - ], - }, - 3: { - 293: [ - (0, Some(8)), - ], - 335: [ - (0, Some(7)), - ], - 364: [ - (12, Some(13)), - ], - 547: [ - (12, Some(17)), - ], - 569: [ - (8, Some(13)), - ], - }, - 5: { - 450: [ - (10, Some(14)), - ], - 495: [ - (8, Some(12)), - ], - 576: [ - (8, None), - ], - 660: [ - (0, Some(10)), - ], - }, - }, - 249: { - 9: { - 251: [ - (0, None), - ], - 477: [ - (13, None), - ], - 523: [ - (0, Some(11)), - ], - 560: [ - (4, Some(7)), - ], - }, - 10: { - 341: [ - (6, Some(11)), - ], - 349: [ - (6, None), - ], - 645: [ - (2, Some(6)), - ], - }, - 15: { - 250: [ - (4, Some(6)), - ], - 312: [ - (11, Some(13)), - ], - 448: [ - (12, None), - ], - 547: [ - (0, Some(3)), - ], - 613: [ - (0, Some(9)), - ], - }, - }, - 250: { - 2: { - 345: [ - (7, Some(10)), - ], - 441: [ - (0, Some(16)), - ], - 448: [ - (0, Some(13)), - ], - 450: [ - (10, Some(18)), - ], - 455: [ - (10, Some(18)), - ], - 495: [ - (3, Some(9)), - ], - 505: [ - (13, Some(18)), - ], - 595: [ - (2, Some(15)), - ], - 613: [ - (10, None), - ], - }, - 4: { - 462: [ - (14, Some(15)), - ], - 471: [ - (0, Some(3)), - ], - 559: [ - (10, None), - ], - 560: [ - (4, None), - ], - 584: [ - (0, None), - ], - 660: [ - (9, None), - ], - }, - 5: { - 349: [ - (1, Some(5)), - ], - 495: [ - (3, Some(10)), - ], - 547: [ - (5, Some(12)), - ], - 660: [ - (0, Some(2)), - ], - }, - 7: { - 600: [ - (6, Some(10)), - ], - 660: [ - (3, None), - ], - }, - 9: { - 334: [ - (6, Some(12)), - ], - 348: [ - (0, Some(4)), - ], - 650: [ - (2, Some(8)), - ], - }, - 10: { - 287: [ - (0, Some(10)), - ], - 297: [ - (17, None), - ], - 334: [ - (0, Some(16)), - ], - 364: [ - (0, Some(11)), - ], - 370: [ - (0, None), - ], - }, - 11: { - 410: [ - (9, Some(17)), - ], - 445: [ - (0, Some(6)), - ], - 523: [ - (6, Some(10)), - ], - 595: [ - (10, Some(11)), - ], - }, - 12: { - 293: [ - (7, Some(11)), - ], - 335: [ - (1, Some(16)), - ], - }, - 14: { - 287: [ - (8, Some(10)), - ], - 462: [ - (2, Some(13)), - ], - 477: [ - (7, Some(8)), - ], - 523: [ - (0, Some(7)), - ], - }, - 15: { - 352: [ - (17, None), - ], - 484: [ - (11, None), - ], - 627: [ - (12, Some(13)), - ], - }, - 17: { - 341: [ - (2, Some(7)), - ], - 450: [ - (16, None), - ], - 479: [ - (0, None), - ], - 560: [ - (0, Some(3)), - ], - 574: [ - (9, Some(11)), - ], - }, - 18: { - 265: [ - (0, Some(10)), - ], - 312: [ - (2, Some(14)), - ], - 491: [ - (2, Some(4)), - ], - 593: [ - (8, Some(10)), - ], - 600: [ - (9, None), - ], - 608: [ - (0, Some(10)), - ], - }, - 19: { - 335: [ - (12, Some(16)), - ], - 349: [ - (1, Some(6)), - ], - 405: [ - (10, None), - ], - }, - }, - 255: { - 5: { - 348: [ - (4, Some(5)), - ], - 396: [ - (7, None), - ], - 441: [ - (8, Some(9)), - ], - 535: [ - (0, Some(7)), - ], - }, - 8: { - 312: [ - (2, Some(14)), - ], - }, - 11: { - 349: [ - (11, Some(13)), - ], - 448: [ - (0, Some(13)), - ], - 462: [ - (3, Some(8)), - ], - 535: [ - (12, Some(14)), - ], - }, - 13: { - 405: [ - (9, Some(10)), - ], - 574: [ - (0, Some(19)), - ], - 608: [ - (12, None), - ], - 645: [ - (16, Some(17)), - ], - }, - 14: { - 265: [ - (12, Some(13)), - ], - 348: [ - (9, None), - ], - 370: [ - (0, None), - ], - 541: [ - (7, Some(9)), - ], - }, - 16: { - 348: [ - (13, Some(17)), - ], - 349: [ - (4, None), - ], - 625: [ - (6, None), - ], - }, - }, - 259: { - 0: { - 341: [ - (0, Some(2)), - ], - 348: [ - (12, Some(18)), - ], - 349: [ - (1, None), - ], - 535: [ - (5, Some(13)), - ], - 593: [ - (4, Some(9)), - ], - 600: [ - (9, None), - ], - 601: [ - (4, Some(7)), - ], - }, - 5: { - 262: [ - (5, None), - ], - 287: [ - (1, None), - ], - }, - 10: { - 662: [ - (7, Some(9)), - ], - }, - 11: { - 341: [ - (7, Some(15)), - ], - 345: [ - (1, Some(4)), - ], - 405: [ - (0, Some(15)), - ], - 448: [ - (11, Some(17)), - ], - 593: [ - (4, None), - ], - }, - 12: { - 352: [ - (10, Some(15)), - ], - 541: [ - (15, Some(17)), - ], - 601: [ - (12, None), - ], - }, - }, - 265: { - 6: { - 405: [ - (7, Some(11)), - ], - 455: [ - (15, Some(16)), - ], - 462: [ - (14, None), - ], - 576: [ - (0, Some(16)), - ], - }, - 7: { - 455: [ - (0, Some(9)), - ], - 535: [ - (5, Some(16)), - ], - 613: [ - (0, Some(4)), - ], - 619: [ - (2, Some(9)), - ], - 650: [ - (0, Some(8)), - ], - }, - 9: { - 448: [ - (15, Some(16)), - ], - 523: [ - (10, Some(19)), - ], - 562: [ - (4, Some(13)), - ], - 601: [ - (4, Some(16)), - ], - }, - 11: { - 316: [ - (6, Some(11)), - ], - }, - 12: { - 352: [ - (10, Some(15)), - ], - 593: [ - (11, Some(14)), - ], - 601: [ - (15, None), - ], - 619: [ - (0, Some(9)), - ], - }, - 18: { - 335: [ - (6, Some(19)), - ], - 345: [ - (1, Some(11)), - ], - 349: [ - (0, Some(7)), - ], - 574: [ - (1, Some(9)), - ], - }, - 19: { - 396: [ - (4, Some(16)), - ], - 462: [ - (12, Some(13)), - ], - }, - }, - 287: { - 0: { - 400: [ - (4, None), - ], - 576: [ - (16, Some(18)), - ], - }, - 1: { - 437: [ - (0, None), - ], - 500: [ - (0, Some(3)), - ], - 505: [ - (6, Some(14)), - ], - 589: [ - (1, Some(7)), - ], - }, - 2: { - 312: [ - (9, Some(11)), - ], - }, - 3: { - 328: [ - (9, None), - ], - 418: [ - (0, Some(1)), - ], - }, - 5: { - 335: [ - (6, None), - ], - 495: [ - (5, None), - ], - 595: [ - (0, None), - ], - 662: [ - (17, Some(19)), - ], - }, - 6: { - 364: [ - (4, None), - ], - 441: [ - (0, Some(14)), - ], - 589: [ - (6, Some(11)), - ], - }, - 8: { - 341: [ - (0, Some(11)), - ], - 349: [ - (0, Some(6)), - ], - 523: [ - (0, Some(1)), - ], - }, - 9: { - 477: [ - (1, Some(13)), - ], - 484: [ - (17, Some(18)), - ], - 584: [ - (11, None), - ], - 601: [ - (16, Some(18)), - ], - }, - 11: { - 312: [ - (10, Some(11)), - ], - 341: [ - (0, Some(8)), - ], - 346: [ - (2, Some(14)), - ], - 371: [ - (12, Some(19)), - ], - 385: [ - (19, None), - ], - 569: [ - (0, Some(19)), - ], - }, - 12: { - 335: [ - (1, Some(3)), - ], - 349: [ - (0, Some(13)), - ], - 462: [ - (2, None), - ], - 541: [ - (15, None), - ], - 562: [ - (11, None), - ], - }, - 13: { - 316: [ - (0, Some(4)), - ], - 334: [ - (6, Some(16)), - ], - 396: [ - (9, Some(15)), - ], - }, - 14: { - 334: [ - (3, Some(8)), - ], - 335: [ - (1, Some(7)), - ], - 341: [ - (6, Some(12)), - ], - 410: [ - (7, Some(17)), - ], - 535: [ - (0, None), - ], - 562: [ - (18, None), - ], - 593: [ - (8, Some(12)), - ], - }, - 16: { - 562: [ - (4, Some(9)), - ], - }, - 19: { - 328: [ - (9, None), - ], - 396: [ - (5, Some(19)), - ], - 562: [ - (4, Some(9)), - ], - }, - }, - 293: { - 3: { - 344: [ - (19, None), - ], - 443: [ - (14, None), - ], - 600: [ - (6, Some(13)), - ], - }, - 7: { - 593: [ - (4, Some(9)), - ], - }, - 10: { - 328: [ - (13, Some(14)), - ], - 450: [ - (6, Some(8)), - ], - 574: [ - (4, Some(11)), - ], - }, - 11: { - 364: [ - (12, Some(13)), - ], - 443: [ - (12, Some(15)), - ], - 662: [ - (0, None), - ], - }, - 12: { - 326: [ - (0, Some(16)), - ], - 334: [ - (3, Some(16)), - ], - 455: [ - (8, Some(16)), - ], - }, - }, - 312: { - 0: { - 326: [ - (16, None), - ], - 505: [ - (1, Some(18)), - ], - }, - 1: { - 448: [ - (0, Some(17)), - ], - }, - 2: { - 462: [ - (3, Some(7)), - ], - 523: [ - (13, Some(15)), - ], - 560: [ - (0, Some(9)), - ], - 593: [ - (11, Some(13)), - ], - 594: [ - (11, Some(12)), - ], - 599: [ - (1, Some(2)), - ], - 627: [ - (14, Some(16)), - ], - }, - 3: { - 348: [ - (8, Some(14)), - ], - 455: [ - (8, None), - ], - 535: [ - (5, Some(6)), - ], - 541: [ - (0, Some(8)), - ], - 569: [ - (6, Some(10)), - ], - 589: [ - (7, Some(11)), - ], - 599: [ - (1, Some(15)), - ], - 601: [ - (19, None), - ], - 627: [ - (11, Some(18)), - ], - }, - 4: { - 335: [ - (0, Some(9)), - ], - 500: [ - (12, Some(13)), - ], - 547: [ - (0, Some(14)), - ], - 584: [ - (11, Some(12)), - ], - 594: [ - (4, None), - ], - 606: [ - (19, None), - ], - 619: [ - (14, Some(15)), - ], - }, - 6: { - 445: [ - (5, Some(9)), - ], - 491: [ - (3, Some(6)), - ], - 523: [ - (1, Some(19)), - ], - 599: [ - (1, Some(3)), - ], - 635: [ - (1, Some(18)), - ], - }, - 9: { - 547: [ - (3, Some(18)), - ], - 559: [ - (8, Some(10)), - ], - 662: [ - (6, Some(18)), - ], - }, - 10: { - 448: [ - (13, None), - ], - 601: [ - (6, Some(9)), - ], - }, - 11: { - 316: [ - (0, Some(3)), - ], - 523: [ - (9, Some(11)), - ], - 560: [ - (0, Some(9)), - ], - 593: [ - (8, Some(12)), - ], - 608: [ - (17, None), - ], - }, - 12: { - 341: [ - (6, None), - ], - 443: [ - (12, None), - ], - }, - 13: { - 345: [ - (4, Some(11)), - ], - 348: [ - (4, Some(17)), - ], - 484: [ - (10, Some(15)), - ], - 562: [ - (0, Some(15)), - ], - 594: [ - (0, Some(2)), - ], - 619: [ - (8, Some(15)), - ], - }, - 15: { - 352: [ - (10, Some(15)), - ], - }, - 16: { - 335: [ - (12, None), - ], - 352: [ - (14, None), - ], - 462: [ - (2, Some(4)), - ], - 484: [ - (4, Some(15)), - ], - 562: [ - (10, Some(13)), - ], - 589: [ - (0, Some(11)), - ], - 599: [ - (6, Some(13)), - ], - 619: [ - (10, Some(15)), - ], - }, - }, - 316: { - 2: { - 396: [ - (5, Some(11)), - ], - 448: [ - (11, None), - ], - 505: [ - (2, Some(3)), - ], - 574: [ - (14, Some(19)), - ], - 601: [ - (6, Some(7)), - ], - 625: [ - (8, None), - ], - }, - 3: { - 619: [ - (2, Some(9)), - ], - 662: [ - (17, Some(19)), - ], - }, - 6: { - 450: [ - (6, None), - ], - 635: [ - (5, Some(15)), - ], - }, - 10: { - 349: [ - (6, Some(8)), - ], - 500: [ - (5, Some(13)), - ], - 505: [ - (10, Some(14)), - ], - 627: [ - (11, Some(19)), - ], - }, - 13: { - 346: [ - (2, Some(17)), - ], - 396: [ - (15, Some(18)), - ], - 410: [ - (0, Some(10)), - ], - 450: [ - (6, Some(15)), - ], - 475: [ - (0, None), - ], - 494: [ - (0, Some(6)), - ], - }, - 14: { - 662: [ - (17, None), - ], - }, - 16: { - 484: [ - (11, None), - ], - 495: [ - (5, Some(12)), - ], - 505: [ - (6, Some(10)), - ], - }, - 17: { - 335: [ - (2, None), - ], - 344: [ - (6, Some(10)), - ], - 541: [ - (13, None), - ], - }, - 19: { - 341: [ - (6, Some(11)), - ], - 370: [ - (0, None), - ], - 371: [ - (12, Some(14)), - ], - 495: [ - (11, Some(13)), - ], - 600: [ - (6, None), - ], - }, - }, - 328: { - 0: { - 352: [ - (15, None), - ], - 541: [ - (6, Some(17)), - ], - }, - 1: { - 334: [ - (3, Some(9)), - ], - 650: [ - (0, Some(3)), - ], - }, - 5: { - 396: [ - (7, Some(19)), - ], - }, - 9: { - 345: [ - (0, Some(4)), - ], - 448: [ - (11, None), - ], - 450: [ - (17, None), - ], - 535: [ - (8, Some(13)), - ], - 600: [ - (6, Some(8)), - ], - }, - 12: {}, - 13: { - 410: [ - (5, Some(10)), - ], - 441: [ - (13, Some(16)), - ], - 595: [ - (10, Some(16)), - ], - 627: [ - (0, None), - ], - }, - 15: { - 348: [ - (3, Some(14)), - ], - 396: [ - (7, Some(15)), - ], - 455: [ - (12, Some(17)), - ], - 589: [ - (6, Some(8)), - ], - }, - 18: { - 396: [ - (10, Some(12)), - ], - 450: [ - (3, Some(4)), - ], - 455: [ - (8, Some(11)), - ], - 535: [ - (13, None), - ], - 569: [ - (8, Some(10)), - ], - 584: [ - (15, None), - ], - 594: [ - (0, Some(6)), - ], - 601: [ - (5, Some(18)), - ], - 613: [ - (8, Some(11)), - ], - }, - }, - 334: { - 0: { - 405: [ - (0, Some(10)), - ], - 599: [ - (12, Some(15)), - ], - 613: [ - (16, None), - ], - }, - 1: { - 396: [ - (17, Some(19)), - ], - 477: [ - (1, Some(16)), - ], - 484: [ - (14, None), - ], - 491: [ - (18, None), - ], - 541: [ - (6, Some(15)), - ], - 662: [ - (3, Some(8)), - ], - }, - 3: { - 450: [ - (7, Some(15)), - ], - 477: [ - (1, Some(14)), - ], - 535: [ - (5, Some(16)), - ], - 569: [ - (12, Some(19)), - ], - 645: [ - (2, Some(7)), - ], - }, - 5: { - 418: [ - (0, None), - ], - 455: [ - (4, Some(10)), - ], - }, - 6: { - 410: [ - (5, Some(14)), - ], - 418: [ - (0, Some(4)), - ], - 462: [ - (2, Some(5)), - ], - }, - 7: { - 405: [ - (2, Some(7)), - ], - 593: [ - (0, None), - ], - 662: [ - (0, Some(4)), - ], - }, - 8: { - 348: [ - (4, None), - ], - 437: [ - (0, Some(16)), - ], - 484: [ - (11, Some(15)), - ], - 491: [ - (0, Some(4)), - ], - 627: [ - (12, None), - ], - }, - 11: { - 349: [ - (1, Some(12)), - ], - 491: [ - (5, Some(7)), - ], - 660: [ - (0, Some(2)), - ], - }, - 15: { - 364: [ - (4, Some(13)), - ], - 601: [ - (6, Some(18)), - ], - 662: [ - (15, Some(17)), - ], - }, - 19: { - 647: [ - (11, None), - ], - }, - }, - 335: { - 0: { - 601: [ - (1, None), - ], - }, - 1: { - 455: [ - (0, Some(18)), - ], - 495: [ - (3, Some(13)), - ], - 569: [ - (16, Some(19)), - ], - }, - 2: { - 448: [ - (11, Some(17)), - ], - 625: [ - (0, Some(9)), - ], - 660: [ - (0, Some(4)), - ], - }, - 3: { - 346: [ - (12, Some(15)), - ], - 443: [ - (12, None), - ], - 455: [ - (4, Some(9)), - ], - 475: [ - (9, None), - ], - 523: [ - (0, Some(9)), - ], - }, - 6: { - 345: [ - (3, Some(15)), - ], - 396: [ - (0, Some(4)), - ], - 505: [ - (0, Some(7)), - ], - }, - 7: { - 455: [ - (17, None), - ], - 477: [ - (13, Some(14)), - ], - }, - 8: { - 599: [ - (7, Some(14)), - ], - }, - 11: { - 547: [ - (3, Some(6)), - ], - 600: [ - (0, Some(9)), - ], - 627: [ - (7, None), - ], - }, - 12: { - 445: [ - (0, Some(9)), - ], - }, - 15: { - 462: [ - (4, None), - ], - }, - 16: { - 405: [ - (7, None), - ], - 471: [ - (0, Some(3)), - ], - 627: [ - (7, Some(12)), - ], - }, - 17: { - 396: [ - (10, Some(18)), - ], - 418: [ - (3, Some(19)), - ], - 574: [ - (11, Some(19)), - ], - 645: [ - (5, None), - ], - }, - 18: { - 345: [ - (10, Some(15)), - ], - 471: [ - (0, Some(2)), - ], - 584: [ - (0, Some(12)), - ], - 589: [ - (8, Some(9)), - ], - }, - 19: { - 344: [ - (13, Some(16)), - ], - 345: [ - (9, None), - ], - 547: [ - (17, None), - ], - 574: [ - (14, None), - ], - 584: [ - (3, None), - ], - }, - }, - 341: { - 1: { - 348: [ - (16, Some(18)), - ], - 370: [ - (0, None), - ], - 479: [ - (0, None), - ], - 574: [ - (4, Some(11)), - ], - 593: [ - (11, None), - ], - }, - 2: { - 346: [ - (0, Some(5)), - ], - 364: [ - (9, Some(12)), - ], - 450: [ - (6, Some(15)), - ], - }, - 6: { - 348: [ - (10, Some(13)), - ], - 484: [ - (14, None), - ], - 494: [ - (5, None), - ], - 595: [ - (14, None), - ], - }, - 7: { - 447: [ - (11, None), - ], - 627: [ - (7, Some(12)), - ], - }, - 10: { - 505: [ - (2, None), - ], - 576: [ - (0, Some(16)), - ], - }, - 11: { - 348: [ - (0, Some(11)), - ], - 364: [ - (4, Some(8)), - ], - 541: [ - (7, Some(8)), - ], - }, - 14: { - 348: [ - (4, Some(16)), - ], - 445: [ - (8, None), - ], - 448: [ - (13, Some(16)), - ], - 600: [ - (12, Some(13)), - ], - }, - 16: { - 535: [ - (16, None), - ], - 547: [ - (0, Some(19)), - ], - 601: [ - (16, None), - ], - }, - 17: { - 396: [ - (4, Some(16)), - ], - 477: [ - (4, Some(16)), - ], - 569: [ - (13, None), - ], - }, - }, - 344: { - 2: { - 396: [ - (14, Some(19)), - ], - 477: [ - (4, None), - ], - 576: [ - (8, Some(11)), - ], - 647: [ - (0, Some(4)), - ], - }, - 3: { - 405: [ - (1, Some(14)), - ], - 574: [ - (8, Some(11)), - ], - }, - 6: { - 364: [ - (5, Some(13)), - ], - 599: [ - (7, Some(15)), - ], - }, - 9: { - 450: [ - (13, Some(17)), - ], - }, - 13: { - 345: [ - (4, Some(12)), - ], - 352: [ - (0, Some(10)), - ], - 475: [ - (3, None), - ], - 560: [ - (4, Some(9)), - ], - 594: [ - (4, Some(12)), - ], - }, - 14: { - 348: [ - (0, Some(12)), - ], - 441: [ - (0, Some(9)), - ], - 443: [ - (12, None), - ], - 462: [ - (14, None), - ], - 523: [ - (10, Some(12)), - ], - 599: [ - (7, Some(14)), - ], - }, - 15: { - 349: [ - (7, Some(13)), - ], - 437: [ - (15, None), - ], - }, - 19: { - 352: [ - (9, Some(16)), - ], - 625: [ - (6, Some(9)), - ], - }, - }, - 345: { - 0: { - 441: [ - (8, None), - ], - 601: [ - (0, Some(5)), - ], - 635: [ - (1, None), - ], - }, - 1: { - 349: [ - (5, Some(11)), - ], - 364: [ - (5, Some(11)), - ], - 371: [ - (0, Some(12)), - ], - 491: [ - (0, Some(4)), - ], - 569: [ - (8, Some(19)), - ], - 627: [ - (12, Some(18)), - ], - }, - 3: { - 405: [ - (4, Some(11)), - ], - 450: [ - (0, Some(17)), - ], - 475: [ - (0, None), - ], - 541: [ - (8, Some(15)), - ], - }, - 4: { - 349: [ - (10, Some(13)), - ], - 405: [ - (10, Some(14)), - ], - 418: [ - (0, Some(9)), - ], - 462: [ - (3, Some(5)), - ], - 523: [ - (1, Some(2)), - ], - 535: [ - (5, None), - ], - 595: [ - (10, Some(16)), - ], - }, - 6: { - 455: [ - (7, Some(18)), - ], - 495: [ - (0, Some(10)), - ], - 569: [ - (13, Some(17)), - ], - }, - 7: { - 471: [ - (2, None), - ], - 535: [ - (6, Some(14)), - ], - }, - 9: { - 447: [ - (8, Some(12)), - ], - 595: [ - (10, Some(16)), - ], - }, - 10: { - 396: [ - (3, Some(8)), - ], - 455: [ - (10, Some(17)), - ], - 523: [ - (0, Some(14)), - ], - 562: [ - (11, Some(12)), - ], - }, - 11: {}, - 13: { - 562: [ - (0, Some(18)), - ], - }, - 14: { - 346: [ - (2, Some(13)), - ], - 445: [ - (0, None), - ], - 484: [ - (16, None), - ], - }, - 17: { - 364: [ - (5, Some(13)), - ], - }, - 18: { - 349: [ - (1, Some(8)), - ], - 410: [ - (0, Some(14)), - ], - 448: [ - (13, None), - ], - 491: [ - (6, None), - ], - 627: [ - (11, Some(12)), - ], - }, - 19: { - 437: [ - (0, None), - ], - 523: [ - (10, None), - ], - 541: [ - (8, None), - ], - 601: [ - (6, Some(13)), - ], - 662: [ - (7, Some(19)), - ], - }, - }, - 346: { - 1: { - 400: [ - (4, Some(5)), - ], - 560: [ - (4, Some(5)), - ], - 574: [ - (10, Some(15)), - ], - 662: [ - (15, Some(17)), - ], - }, - 2: { - 396: [ - (9, Some(16)), - ], - 455: [ - (8, Some(10)), - ], - 484: [ - (10, Some(17)), - ], - 535: [ - (13, Some(14)), - ], - }, - 4: { - 455: [ - (4, Some(5)), - ], - 484: [ - (2, Some(17)), - ], - 495: [ - (4, Some(10)), - ], - 535: [ - (6, Some(13)), - ], - 608: [ - (0, None), - ], - }, - 6: { - 349: [ - (1, Some(5)), - ], - 599: [ - (14, None), - ], - 608: [ - (6, Some(13)), - ], - 635: [ - (17, None), - ], - }, - 10: {}, - 12: { - 505: [ - (13, Some(18)), - ], - 627: [ - (7, Some(15)), - ], - }, - 13: { - 352: [ - (0, Some(16)), - ], - 437: [ - (0, Some(12)), - ], - 448: [ - (16, Some(17)), - ], - 600: [ - (9, Some(10)), - ], - 635: [ - (5, None), - ], - 662: [ - (0, Some(18)), - ], - }, - 14: { - 500: [ - (5, Some(13)), - ], - 589: [ - (7, Some(11)), - ], - }, - 16: { - 418: [ - (3, Some(17)), - ], - 455: [ - (8, Some(17)), - ], - 660: [ - (3, Some(10)), - ], - }, - 18: { - 666: [ - (0, None), - ], - }, - 19: { - 349: [ - (4, Some(9)), - ], - 351: [ - (0, Some(7)), - ], - 450: [ - (16, Some(17)), - ], - }, - }, - 348: { - 2: { - 484: [ - (0, Some(5)), - ], - }, - 3: { - 385: [ - (5, None), - ], - 400: [ - (0, None), - ], - 477: [ - (1, Some(13)), - ], - 608: [ - (0, None), - ], - 613: [ - (10, None), - ], - }, - 4: { - 484: [ - (7, Some(11)), - ], - 491: [ - (0, None), - ], - 593: [ - (0, Some(13)), - ], - 619: [ - (2, None), - ], - 627: [ - (11, Some(19)), - ], - }, - 7: { - 370: [ - (16, None), - ], - 418: [ - (19, None), - ], - 500: [ - (5, Some(13)), - ], - 547: [ - (11, Some(14)), - ], - 594: [ - (4, Some(6)), - ], - 595: [ - (2, Some(11)), - ], - }, - 8: { - 505: [ - (13, None), - ], - 547: [ - (2, Some(4)), - ], - 559: [ - (8, Some(9)), - ], - 560: [ - (2, None), - ], - 562: [ - (10, Some(12)), - ], - 594: [ - (1, None), - ], - }, - 9: { - 418: [ - (0, Some(19)), - ], - 477: [ - (18, None), - ], - 505: [ - (0, Some(11)), - ], - 574: [ - (1, None), - ], - }, - 10: { - 349: [ - (5, Some(13)), - ], - 471: [ - (2, Some(3)), - ], - }, - 11: { - 494: [ - (0, Some(2)), - ], - }, - 12: { - 541: [ - (16, None), - ], - 599: [ - (1, Some(8)), - ], - }, - 13: { - 600: [ - (6, Some(10)), - ], - 635: [ - (1, None), - ], - 650: [ - (7, None), - ], - }, - 14: { - 437: [ - (0, Some(12)), - ], - 594: [ - (1, Some(12)), - ], - }, - 15: { - 477: [ - (1, Some(3)), - ], - 500: [ - (16, None), - ], - }, - 16: { - 405: [ - (4, Some(15)), - ], - 523: [ - (8, Some(11)), - ], - 595: [ - (10, None), - ], - 606: [ - (7, Some(8)), - ], - 625: [ - (0, Some(2)), - ], - }, - 17: { - 495: [ - (9, None), - ], - }, - 18: {}, - }, - 349: { - 0: { - 352: [ - (10, Some(17)), - ], - 599: [ - (1, Some(14)), - ], - 601: [ - (14, Some(17)), - ], - }, - 1: { - 559: [ - (9, Some(13)), - ], - 593: [ - (0, Some(12)), - ], - }, - 2: { - 396: [ - (4, Some(12)), - ], - 600: [ - (9, None), - ], - }, - 3: {}, - 4: { - 450: [ - (3, Some(6)), - ], - 505: [ - (1, Some(3)), - ], - 547: [ - (0, Some(3)), - ], - }, - 5: { - 484: [ - (4, Some(5)), - ], - 541: [ - (15, Some(16)), - ], - 627: [ - (7, Some(8)), - ], - }, - 6: { - 500: [ - (0, Some(6)), - ], - 625: [ - (6, Some(9)), - ], - }, - 7: { - 418: [ - (19, None), - ], - 541: [ - (7, Some(9)), - ], - 601: [ - (17, None), - ], - }, - 8: { - 445: [ - (0, Some(6)), - ], - 450: [ - (4, Some(8)), - ], - 541: [ - (8, Some(9)), - ], - 547: [ - (3, Some(13)), - ], - 600: [ - (18, None), - ], - 601: [ - (0, Some(5)), - ], - 619: [ - (0, Some(5)), - ], - }, - 9: { - 396: [ - (0, Some(15)), - ], - 405: [ - (1, Some(2)), - ], - }, - 10: { - 627: [ - (17, Some(18)), - ], - }, - 11: { - 495: [ - (0, Some(9)), - ], - 523: [ - (8, Some(11)), - ], - }, - 12: { - 477: [ - (0, Some(3)), - ], - }, - 14: { - 385: [ - (0, Some(6)), - ], - 576: [ - (8, Some(18)), - ], - 589: [ - (0, Some(8)), - ], - 608: [ - (0, Some(7)), - ], - 662: [ - (3, Some(8)), - ], - }, - 17: { - 396: [ - (15, Some(18)), - ], - 455: [ - (4, Some(16)), - ], - }, - }, - 352: { - 5: {}, - 6: { - 477: [ - (9, Some(14)), - ], - 562: [ - (12, None), - ], - }, - 9: { - 601: [ - (1, Some(6)), - ], - }, - 10: { - 574: [ - (8, Some(10)), - ], - }, - 14: { - 437: [ - (15, Some(16)), - ], - 584: [ - (3, Some(12)), - ], - 647: [ - (0, None), - ], - }, - 15: { - 477: [ - (1, Some(14)), - ], - 560: [ - (0, Some(7)), - ], - 594: [ - (1, None), - ], - }, - 16: { - 613: [ - (8, None), - ], - }, - 17: { - 477: [ - (12, Some(14)), - ], - 484: [ - (16, Some(18)), - ], - 547: [ - (0, Some(5)), - ], - 593: [ - (4, Some(13)), - ], - 613: [ - (10, None), - ], - }, - }, - 364: { - 0: { - 562: [ - (8, Some(18)), - ], - }, - 4: { - 523: [ - (1, Some(7)), - ], - }, - 5: { - 601: [ - (4, Some(9)), - ], - 645: [ - (6, None), - ], - }, - 7: { - 396: [ - (3, Some(11)), - ], - }, - 9: { - 595: [ - (2, Some(15)), - ], - }, - 10: {}, - 11: {}, - 12: { - 437: [ - (0, None), - ], - 455: [ - (0, Some(18)), - ], - 484: [ - (8, Some(11)), - ], - 601: [ - (1, Some(13)), - ], - }, - 14: { - 589: [ - (7, Some(8)), - ], - }, - }, - 371: { - 9: { - 400: [ - (0, Some(1)), - ], - 455: [ - (0, Some(9)), - ], - 477: [ - (9, Some(16)), - ], - 645: [ - (0, Some(7)), - ], - }, - 11: { - 405: [ - (5, Some(7)), - ], - 410: [ - (0, Some(6)), - ], - 547: [ - (12, Some(13)), - ], - 574: [ - (2, Some(12)), - ], - 576: [ - (0, Some(18)), - ], - 589: [ - (6, Some(8)), - ], - }, - 12: { - 443: [ - (0, Some(15)), - ], - 475: [ - (0, Some(4)), - ], - 547: [ - (0, Some(14)), - ], - 562: [ - (10, Some(18)), - ], - }, - 13: { - 400: [ - (0, Some(1)), - ], - 601: [ - (4, Some(15)), - ], - }, - 18: { - 455: [ - (7, Some(13)), - ], - 627: [ - (0, Some(16)), - ], - }, - 19: { - 495: [ - (0, Some(10)), - ], - 505: [ - (0, Some(11)), - ], - 523: [ - (11, Some(15)), - ], - }, - }, - 396: { - 1: { - 477: [ - (4, Some(10)), - ], - 574: [ - (1, Some(19)), - ], - 606: [ - (16, None), - ], - }, - 3: { - 562: [ - (8, Some(18)), - ], - 569: [ - (0, Some(17)), - ], - 576: [ - (15, None), - ], - }, - 4: { - 535: [ - (8, Some(14)), - ], - 589: [ - (1, Some(9)), - ], - 627: [ - (17, None), - ], - }, - 5: { - 484: [ - (14, Some(18)), - ], - }, - 7: { - 562: [ - (12, None), - ], - 608: [ - (0, None), - ], - }, - 9: { - 448: [ - (15, Some(17)), - ], - 523: [ - (9, Some(10)), - ], - 660: [ - (0, None), - ], - }, - 10: { - 484: [ - (0, Some(15)), - ], - 547: [ - (11, Some(13)), - ], - 619: [ - (2, Some(9)), - ], - }, - 11: { - 441: [ - (8, Some(16)), - ], - 589: [ - (7, Some(11)), - ], - }, - 14: { - 535: [ - (12, None), - ], - 650: [ - (2, Some(15)), - ], - }, - 15: { - 418: [ - (18, None), - ], - 495: [ - (11, Some(13)), - ], - 523: [ - (8, Some(14)), - ], - 547: [ - (11, Some(19)), - ], - 627: [ - (17, None), - ], - 650: [ - (0, Some(15)), - ], - }, - 17: { - 441: [ - (15, None), - ], - }, - 18: { - 443: [ - (0, Some(1)), - ], - 662: [ - (16, Some(18)), - ], - }, - 19: { - 443: [ - (12, Some(15)), - ], - 593: [ - (0, Some(5)), - ], - }, - }, - 400: { - 0: { - 443: [ - (0, Some(13)), - ], - 462: [ - (4, Some(5)), - ], - }, - 4: { - 666: [ - (0, None), - ], - }, - 9: { - 462: [ - (14, None), - ], - 599: [ - (0, Some(3)), - ], - 600: [ - (6, Some(8)), - ], - }, - }, - 405: { - 0: { - 455: [ - (8, Some(9)), - ], - 599: [ - (7, Some(15)), - ], - 625: [ - (6, Some(7)), - ], - }, - 1: { - 484: [ - (16, Some(17)), - ], - 594: [ - (1, Some(6)), - ], - 662: [ - (16, Some(18)), - ], - }, - 2: { - 410: [ - (0, None), - ], - 477: [ - (12, Some(16)), - ], - 484: [ - (4, Some(9)), - ], - 601: [ - (12, Some(17)), - ], - }, - 4: { - 450: [ - (4, Some(17)), - ], - 462: [ - (2, Some(7)), - ], - 495: [ - (0, None), - ], - 559: [ - (0, None), - ], - 562: [ - (8, Some(13)), - ], - }, - 5: { - 447: [ - (8, Some(12)), - ], - 477: [ - (12, None), - ], - 600: [ - (6, None), - ], - }, - 6: { - 495: [ - (0, Some(6)), - ], - 594: [ - (12, None), - ], - 635: [ - (14, Some(16)), - ], - }, - 7: { - 547: [ - (2, Some(12)), - ], - 562: [ - (10, Some(15)), - ], - }, - 9: { - 635: [ - (4, Some(10)), - ], - }, - 10: { - 547: [ - (5, Some(19)), - ], - 559: [ - (0, Some(12)), - ], - }, - 11: {}, - 13: { - 450: [ - (3, Some(17)), - ], - 523: [ - (9, Some(15)), - ], - 562: [ - (11, Some(15)), - ], - 574: [ - (10, None), - ], - 627: [ - (7, Some(19)), - ], - }, - 14: { - 600: [ - (0, Some(9)), - ], - 650: [ - (7, Some(15)), - ], - }, - 17: { - 450: [ - (7, Some(17)), - ], - 491: [ - (0, Some(6)), - ], - 505: [ - (2, Some(10)), - ], - }, - }, - 410: { - 3: { - 475: [ - (0, Some(4)), - ], - 484: [ - (10, Some(18)), - ], - 505: [ - (1, Some(18)), - ], - 660: [ - (3, Some(10)), - ], - }, - 5: { - 447: [ - (8, None), - ], - 477: [ - (1, Some(13)), - ], - }, - 7: {}, - 9: { - 569: [ - (12, Some(19)), - ], - }, - 13: { - 491: [ - (5, Some(6)), - ], - 541: [ - (8, None), - ], - }, - 16: { - 484: [ - (0, Some(15)), - ], - 523: [ - (10, Some(14)), - ], - 601: [ - (4, Some(15)), - ], - }, - 18: { - 477: [ - (1, Some(14)), - ], - 595: [ - (0, Some(14)), - ], - }, - }, - 418: { - 0: { - 627: [ - (3, Some(15)), - ], - }, - 3: { - 450: [ - (3, Some(6)), - ], - 535: [ - (13, Some(16)), - ], - 627: [ - (7, Some(13)), - ], - }, - 8: { - 484: [ - (7, Some(8)), - ], - 574: [ - (0, Some(12)), - ], - 601: [ - (12, Some(18)), - ], - }, - 15: { - 441: [ - (0, Some(16)), - ], - 450: [ - (4, None), - ], - }, - 16: { - 662: [ - (0, None), - ], - }, - 18: { - 437: [ - (0, Some(16)), - ], - 576: [ - (8, Some(9)), - ], - 595: [ - (13, Some(17)), - ], - }, - 19: { - 505: [ - (0, Some(2)), - ], - }, - }, - 437: { - 11: { - 450: [ - (6, Some(11)), - ], - }, - 15: { - 535: [ - (8, None), - ], - 541: [ - (13, Some(16)), - ], - 593: [ - (9, Some(12)), - ], - 600: [ - (0, Some(8)), - ], - 635: [ - (9, None), - ], - }, - 16: { - 450: [ - (14, Some(17)), - ], - 475: [ - (9, None), - ], - 500: [ - (0, Some(3)), - ], - 547: [ - (3, Some(17)), - ], - 593: [ - (8, Some(13)), - ], - }, - }, - 441: { - 2: {}, - 8: { - 462: [ - (3, Some(8)), - ], - 491: [ - (3, Some(6)), - ], - }, - 13: { - 445: [ - (8, None), - ], - 569: [ - (0, Some(13)), - ], - }, - 15: { - 455: [ - (4, Some(5)), - ], - 505: [ - (6, Some(14)), - ], - }, - 16: { - 560: [ - (8, None), - ], - 589: [ - (8, Some(11)), - ], - }, - }, - 443: { - 0: { - 447: [ - (0, Some(12)), - ], - 500: [ - (0, None), - ], - 505: [ - (0, Some(18)), - ], - 547: [ - (3, None), - ], - }, - 12: { - 523: [ - (6, Some(19)), - ], - 562: [ - (10, Some(13)), - ], - 606: [ - (0, Some(7)), - ], - }, - 14: { - 450: [ - (3, Some(15)), - ], - 574: [ - (0, Some(2)), - ], - 595: [ - (2, Some(14)), - ], - }, - 17: { - 569: [ - (16, None), - ], - }, - }, - 447: { - 1: { - 541: [ - (8, None), - ], - }, - 8: { - 645: [ - (0, Some(1)), - ], - }, - 11: { - 541: [ - (6, Some(9)), - ], - }, - 13: { - 606: [ - (6, Some(17)), - ], - 662: [ - (6, None), - ], - }, - 14: { - 450: [ - (6, Some(15)), - ], - 500: [ - (0, None), - ], - 541: [ - (6, Some(15)), - ], - }, - }, - 448: { - 3: { - 562: [ - (8, Some(11)), - ], - 662: [ - (6, Some(18)), - ], - }, - 11: { - 450: [ - (0, Some(17)), - ], - 455: [ - (10, Some(16)), - ], - 477: [ - (0, None), - ], - 505: [ - (1, Some(7)), - ], - 601: [ - (1, Some(5)), - ], - 625: [ - (4, Some(7)), - ], - 650: [ - (0, Some(15)), - ], - 660: [ - (0, None), - ], - }, - 12: { - 562: [ - (0, Some(15)), - ], - }, - 13: { - 455: [ - (17, None), - ], - 650: [ - (14, Some(15)), - ], - }, - 15: {}, - 16: { - 660: [ - (0, Some(4)), - ], - }, - 19: { - 484: [ - (7, Some(8)), - ], - 601: [ - (4, Some(7)), - ], - }, - }, - 450: { - 2: { - 601: [ - (1, Some(18)), - ], - }, - 3: { - 505: [ - (1, Some(2)), - ], - }, - 4: {}, - 5: { - 484: [ - (8, Some(17)), - ], - 547: [ - (4, Some(13)), - ], - 576: [ - (8, None), - ], - 594: [ - (4, None), - ], - }, - 6: { - 645: [ - (5, None), - ], - }, - 7: { - 477: [ - (0, Some(5)), - ], - 593: [ - (9, None), - ], - 645: [ - (16, None), - ], - }, - 10: {}, - 13: { - 495: [ - (3, Some(5)), - ], - }, - 14: { - 471: [ - (2, None), - ], - 495: [ - (9, Some(12)), - ], - 562: [ - (12, Some(15)), - ], - 619: [ - (2, Some(7)), - ], - }, - 16: { - 500: [ - (0, None), - ], - 535: [ - (12, Some(14)), - ], - 594: [ - (4, Some(12)), - ], - }, - 17: { - 560: [ - (0, Some(9)), - ], - 562: [ - (11, None), - ], - 599: [ - (0, Some(2)), - ], - }, - 19: { - 471: [ - (2, None), - ], - 523: [ - (10, Some(14)), - ], - 576: [ - (10, Some(16)), - ], - 645: [ - (2, None), - ], - 662: [ - (7, Some(9)), - ], - }, - }, - 455: { - 2: { - 491: [ - (0, Some(1)), - ], - 559: [ - (10, Some(12)), - ], - 560: [ - (0, None), - ], - }, - 4: { - 600: [ - (0, Some(13)), - ], - }, - 7: { - 484: [ - (14, Some(17)), - ], - 574: [ - (2, Some(15)), - ], - 595: [ - (0, Some(2)), - ], - }, - 8: { - 560: [ - (16, None), - ], - 574: [ - (4, Some(12)), - ], - 599: [ - (7, Some(14)), - ], - }, - 9: { - 562: [ - (14, Some(18)), - ], - 595: [ - (0, Some(14)), - ], - 601: [ - (0, Some(6)), - ], - }, - 10: { - 600: [ - (6, Some(8)), - ], - 613: [ - (16, None), - ], - 662: [ - (3, Some(9)), - ], - }, - 12: { - 666: [ - (0, None), - ], - }, - 15: { - 666: [ - (0, None), - ], - }, - 16: { - 495: [ - (3, Some(4)), - ], - 599: [ - (2, Some(3)), - ], - 650: [ - (2, None), - ], - }, - 17: { - 491: [ - (9, Some(10)), - ], - 569: [ - (13, Some(19)), - ], - 662: [ - (17, Some(19)), - ], - }, - 19: {}, - }, - 462: { - 1: {}, - 2: { - 477: [ - (0, Some(10)), - ], - 574: [ - (2, Some(12)), - ], - 601: [ - (4, Some(17)), - ], - 606: [ - (16, None), - ], - 625: [ - (4, Some(9)), - ], - }, - 3: { - 589: [ - (8, Some(11)), - ], - 608: [ - (9, None), - ], - }, - 4: { - 479: [ - (0, Some(6)), - ], - 635: [ - (1, Some(5)), - ], - }, - 6: { - 535: [ - (6, None), - ], - 599: [ - (12, Some(14)), - ], - 608: [ - (0, Some(5)), - ], - 613: [ - (8, Some(11)), - ], - }, - 7: { - 484: [ - (2, Some(18)), - ], - 574: [ - (4, Some(19)), - ], - 606: [ - (16, Some(17)), - ], - }, - 12: { - 477: [ - (1, Some(8)), - ], - 547: [ - (4, Some(18)), - ], - 574: [ - (19, None), - ], - 593: [ - (8, Some(14)), - ], - }, - 14: { - 491: [ - (3, Some(7)), - ], - }, - 16: { - 608: [ - (0, Some(7)), - ], - }, - }, - 471: { - 1: { - 484: [ - (2, Some(9)), - ], - 569: [ - (8, Some(10)), - ], - 599: [ - (1, Some(13)), - ], - }, - 2: { - 494: [ - (0, None), - ], - 608: [ - (0, None), - ], - }, - 18: { - 484: [ - (4, Some(18)), - ], - 523: [ - (9, Some(10)), - ], - 576: [ - (7, Some(18)), - ], - 662: [ - (8, Some(18)), - ], - }, - }, - 475: { - 0: { - 500: [ - (16, None), - ], - 560: [ - (4, None), - ], - 569: [ - (12, None), - ], - 589: [ - (8, Some(11)), - ], - 608: [ - (6, Some(10)), - ], - }, - 3: { - 599: [ - (1, Some(8)), - ], - 619: [ - (2, Some(15)), - ], - }, - 9: { - 593: [ - (4, Some(13)), - ], - }, - }, - 477: { - 0: { - 505: [ - (1, Some(18)), - ], - 562: [ - (0, Some(13)), - ], - }, - 1: { - 523: [ - (0, Some(15)), - ], - }, - 2: { - 484: [ - (10, Some(12)), - ], - 608: [ - (0, Some(13)), - ], - }, - 4: { - 541: [ - (14, Some(16)), - ], - 601: [ - (0, Some(1)), - ], - }, - 7: { - 569: [ - (0, Some(19)), - ], - 600: [ - (0, None), - ], - }, - 9: { - 484: [ - (2, Some(15)), - ], - 569: [ - (8, Some(19)), - ], - 608: [ - (9, Some(13)), - ], - 645: [ - (5, Some(7)), - ], - 650: [ - (7, Some(15)), - ], - 660: [ - (0, Some(4)), - ], - }, - 12: {}, - 13: { - 495: [ - (3, Some(6)), - ], - 535: [ - (5, Some(7)), - ], - 595: [ - (13, Some(16)), - ], - }, - 15: { - 635: [ - (5, Some(18)), - ], - }, - 18: { - 495: [ - (3, Some(10)), - ], - 562: [ - (4, Some(15)), - ], - 574: [ - (1, Some(19)), - ], - 613: [ - (8, Some(11)), - ], - }, - 19: { - 584: [ - (0, Some(12)), - ], - 600: [ - (9, Some(13)), - ], - 608: [ - (0, Some(5)), - ], - }, - }, - 479: { - 5: { - 523: [ - (10, None), - ], - }, - 14: { - 484: [ - (0, Some(8)), - ], - 589: [ - (1, Some(7)), - ], - }, - }, - 484: { - 0: { - 594: [ - (0, Some(12)), - ], - }, - 2: { - 505: [ - (9, Some(14)), - ], - 535: [ - (13, None), - ], - 560: [ - (2, Some(9)), - ], - 574: [ - (2, Some(5)), - ], - }, - 4: { - 574: [ - (0, Some(1)), - ], - }, - 6: { - 662: [ - (15, Some(17)), - ], - }, - 7: { - 491: [ - (3, Some(4)), - ], - 613: [ - (0, Some(4)), - ], - }, - 8: { - 541: [ - (16, None), - ], - }, - 10: {}, - 11: { - 541: [ - (6, Some(17)), - ], - }, - 14: { - 645: [ - (0, None), - ], - }, - 16: { - 491: [ - (3, None), - ], - 600: [ - (18, None), - ], - 613: [ - (0, Some(4)), - ], - }, - 17: { - 635: [ - (9, Some(18)), - ], - }, - 18: { - 495: [ - (5, Some(10)), - ], - 574: [ - (0, Some(12)), - ], - 601: [ - (0, Some(19)), - ], - }, - }, - 491: { - 0: {}, - 2: { - 595: [ - (16, None), - ], - 662: [ - (15, Some(17)), - ], - }, - 3: { - 547: [ - (17, Some(19)), - ], - }, - 5: { - 595: [ - (14, Some(16)), - ], - 647: [ - (0, Some(4)), - ], - }, - 6: { - 662: [ - (16, Some(18)), - ], - }, - 9: { - 662: [ - (6, None), - ], - }, - 18: { - 569: [ - (6, Some(13)), - ], - 594: [ - (5, Some(6)), - ], - 595: [ - (10, Some(17)), - ], - 635: [ - (14, None), - ], - 662: [ - (17, None), - ], - }, - }, - 494: { - 1: { - 547: [ - (11, Some(19)), - ], - 562: [ - (10, None), - ], - 599: [ - (2, Some(8)), - ], - 619: [ - (6, Some(11)), - ], - }, - 5: { - 574: [ - (8, None), - ], - 601: [ - (0, Some(19)), - ], - }, - 12: { - 495: [ - (11, None), - ], - 601: [ - (16, None), - ], - 645: [ - (6, Some(7)), - ], - }, - }, - 495: { - 1: {}, - 3: { - 608: [ - (6, Some(13)), - ], - }, - 4: {}, - 5: { - 595: [ - (15, Some(17)), - ], - 650: [ - (14, Some(15)), - ], - }, - 8: { - 576: [ - (0, Some(9)), - ], - }, - 9: {}, - 11: { - 547: [ - (6, Some(13)), - ], - 559: [ - (8, Some(12)), - ], - 594: [ - (1, None), - ], - 613: [ - (8, None), - ], - 645: [ - (0, Some(7)), - ], - }, - 12: { - 662: [ - (0, Some(4)), - ], - }, - 16: { - 608: [ - (9, None), - ], - }, - }, - 500: { - 2: { - 613: [ - (8, None), - ], - }, - 5: { - 594: [ - (0, None), - ], - }, - 12: {}, - 16: { - 601: [ - (6, Some(13)), - ], - 627: [ - (17, None), - ], - }, - }, - 505: { - 0: { - 535: [ - (0, Some(14)), - ], - }, - 1: { - 666: [ - (0, None), - ], - }, - 2: { - 535: [ - (8, Some(13)), - ], - 619: [ - (0, Some(5)), - ], - 662: [ - (7, Some(19)), - ], - }, - 6: { - 559: [ - (11, Some(12)), - ], - }, - 9: {}, - 10: { - 589: [ - (1, Some(2)), - ], - 595: [ - (10, None), - ], - }, - 13: { - 584: [ - (11, Some(12)), - ], - 589: [ - (0, Some(8)), - ], - 595: [ - (0, Some(16)), - ], - 600: [ - (0, Some(13)), - ], - 619: [ - (14, Some(15)), - ], - }, - 17: { - 589: [ - (7, Some(8)), - ], - 619: [ - (6, Some(9)), - ], - }, - 18: { - 547: [ - (6, Some(12)), - ], - }, - }, - 523: { - 0: { - 613: [ - (0, None), - ], - }, - 1: { - 608: [ - (0, Some(13)), - ], - 662: [ - (17, Some(19)), - ], - }, - 6: {}, - 8: { - 594: [ - (0, Some(12)), - ], - 600: [ - (6, Some(10)), - ], - }, - 9: { - 562: [ - (17, None), - ], - 569: [ - (6, Some(17)), - ], - }, - 10: {}, - 11: { - 535: [ - (8, None), - ], - 576: [ - (8, Some(16)), - ], - 619: [ - (4, Some(5)), - ], - }, - 13: { - 593: [ - (6, Some(14)), - ], - }, - 14: { - 645: [ - (16, None), - ], - }, - 18: { - 619: [ - (0, Some(5)), - ], - 625: [ - (4, None), - ], - 627: [ - (14, Some(16)), - ], - }, - 19: { - 535: [ - (0, Some(14)), - ], - 650: [ - (0, None), - ], - }, - }, - 535: { - 1: { - 599: [ - (6, Some(11)), - ], - }, - 5: { - 547: [ - (2, Some(14)), - ], - 559: [ - (0, Some(10)), - ], - }, - 6: { - 541: [ - (0, None), - ], - }, - 8: {}, - 12: {}, - 13: { - 635: [ - (5, Some(10)), - ], - 662: [ - (7, Some(9)), - ], - }, - 15: { - 608: [ - (0, Some(7)), - ], - }, - 16: { - 625: [ - (4, Some(9)), - ], - 627: [ - (18, None), - ], - }, - }, - 541: { - 1: { - 601: [ - (1, Some(15)), - ], - }, - 6: {}, - 7: { - 547: [ - (4, Some(19)), - ], - 593: [ - (4, Some(9)), - ], - 650: [ - (14, None), - ], - }, - 8: { - 625: [ - (4, Some(7)), - ], - }, - 13: { - 574: [ - (2, Some(15)), - ], - 589: [ - (1, None), - ], - 635: [ - (14, None), - ], - }, - 14: { - 547: [ - (6, None), - ], - 599: [ - (2, Some(13)), - ], - 627: [ - (17, Some(19)), - ], - }, - 15: { - 547: [ - (0, Some(14)), - ], - 576: [ - (10, None), - ], - 662: [ - (0, Some(4)), - ], - }, - 16: { - 645: [ - (2, Some(7)), - ], - }, - 17: { - 650: [ - (14, None), - ], - }, - }, - 547: { - 0: { - 650: [ - (2, Some(15)), - ], - }, - 2: { - 635: [ - (0, Some(15)), - ], - }, - 3: {}, - 4: { - 635: [ - (5, Some(15)), - ], - 645: [ - (16, Some(17)), - ], - }, - 5: {}, - 6: {}, - 11: { - 574: [ - (1, Some(5)), - ], - 584: [ - (3, Some(4)), - ], - 662: [ - (0, Some(19)), - ], - }, - 12: {}, - 13: { - 589: [ - (8, Some(11)), - ], - 601: [ - (4, Some(16)), - ], - }, - 14: { - 601: [ - (15, Some(17)), - ], - }, - 16: {}, - 17: { - 574: [ - (9, Some(15)), - ], - 650: [ - (7, Some(15)), - ], - 662: [ - (3, Some(19)), - ], - }, - 18: { - 569: [ - (0, None), - ], - 662: [ - (0, Some(8)), - ], - }, - 19: {}, - }, - 559: { - 8: { - 650: [ - (14, None), - ], - }, - 9: { - 560: [ - (4, Some(9)), - ], - }, - 10: {}, - 11: { - 574: [ - (11, None), - ], - }, - 12: {}, - 18: { - 601: [ - (1, Some(15)), - ], - }, - }, - 560: { - 0: { - 589: [ - (1, Some(11)), - ], - 613: [ - (0, Some(9)), - ], - }, - 2: { - 593: [ - (0, Some(13)), - ], - }, - 4: {}, - 6: { - 600: [ - (0, Some(8)), - ], - }, - 8: { - 600: [ - (8, Some(13)), - ], - 635: [ - (4, None), - ], - }, - 16: {}, - }, - 562: { - 0: { - 576: [ - (16, Some(17)), - ], - 593: [ - (6, None), - ], - }, - 4: { - 608: [ - (0, Some(5)), - ], - }, - 8: { - 606: [ - (0, Some(17)), - ], - 645: [ - (0, Some(3)), - ], - }, - 10: {}, - 11: { - 574: [ - (8, None), - ], - 647: [ - (0, None), - ], - }, - 12: {}, - 14: { - 569: [ - (0, Some(10)), - ], - 635: [ - (0, None), - ], - }, - 17: {}, - 18: { - 635: [ - (5, Some(15)), - ], - 662: [ - (8, Some(9)), - ], - }, - }, - 569: { - 3: { - 574: [ - (0, Some(10)), - ], - }, - 6: { - 595: [ - (0, Some(17)), - ], - 601: [ - (8, Some(13)), - ], - 635: [ - (9, Some(16)), - ], - }, - 8: { - 635: [ - (4, Some(16)), - ], - 647: [ - (0, None), - ], - }, - 9: { - 584: [ - (11, None), - ], - }, - 12: { - 627: [ - (0, Some(13)), - ], - }, - 13: { - 589: [ - (10, None), - ], - }, - 16: { - 599: [ - (2, Some(8)), - ], - 645: [ - (0, Some(17)), - ], - }, - 18: { - 574: [ - (14, Some(15)), - ], - 645: [ - (16, Some(17)), - ], - 647: [ - (0, None), - ], - }, - 19: { - 574: [ - (10, None), - ], - 589: [ - (8, Some(11)), - ], - }, - }, - 574: { - 0: { - 593: [ - (0, Some(5)), - ], - }, - 1: { - 600: [ - (9, None), - ], - }, - 2: { - 589: [ - (6, None), - ], - 650: [ - (14, Some(15)), - ], - }, - 4: {}, - 8: { - 635: [ - (4, Some(18)), - ], - }, - 9: {}, - 10: {}, - 11: { - 601: [ - (8, Some(16)), - ], - 625: [ - (4, Some(5)), - ], - }, - 14: { - 576: [ - (15, Some(17)), - ], - 593: [ - (8, None), - ], - 601: [ - (4, None), - ], - }, - 18: { - 650: [ - (0, Some(8)), - ], - }, - 19: {}, - }, - 576: { - 4: { - 645: [ - (5, None), - ], - }, - 7: {}, - 8: {}, - 10: { - 601: [ - (0, Some(15)), - ], - }, - 15: { - 593: [ - (4, Some(12)), - ], - 594: [ - (0, Some(12)), - ], - }, - 16: { - 599: [ - (14, None), - ], - }, - 17: { - 625: [ - (4, Some(7)), - ], - }, - 19: {}, - }, - 584: { - 1: { - 599: [ - (0, Some(2)), - ], - 600: [ - (7, Some(13)), - ], - }, - 3: {}, - 11: {}, - 15: {}, - }, - 589: { - 0: { - 595: [ - (14, None), - ], - }, - 1: {}, - 6: { - 619: [ - (8, Some(9)), - ], - 660: [ - (3, Some(10)), - ], - }, - 7: { - 635: [ - (0, Some(2)), - ], - }, - 8: { - 600: [ - (18, None), - ], - }, - 10: {}, - 15: { - 599: [ - (14, None), - ], - 645: [ - (2, Some(6)), - ], - }, - }, - 593: { - 0: { - 595: [ - (0, Some(14)), - ], - 608: [ - (12, None), - ], - }, - 4: { - 650: [ - (14, None), - ], - }, - 6: { - 625: [ - (0, None), - ], - }, - 8: {}, - 9: {}, - 11: {}, - 12: {}, - 13: {}, - 15: { - 635: [ - (9, Some(15)), - ], - }, - }, - 594: { - 0: { - 613: [ - (8, None), - ], - 619: [ - (2, None), - ], - 662: [ - (16, Some(19)), - ], - }, - 1: { - 625: [ - (10, None), - ], - 647: [ - (0, Some(4)), - ], - }, - 4: {}, - 5: {}, - 11: { - 619: [ - (2, None), - ], - 662: [ - (6, Some(16)), - ], - }, - 12: {}, - }, - 595: { - 1: {}, - 2: {}, - 10: {}, - 13: { - 599: [ - (7, Some(11)), - ], - }, - 14: { - 619: [ - (2, Some(15)), - ], - }, - 15: {}, - 16: {}, - 19: {}, - }, - 599: { - 0: { - 635: [ - (1, Some(10)), - ], - }, - 1: { - 635: [ - (0, Some(10)), - ], - }, - 2: {}, - 6: { - 625: [ - (6, Some(9)), - ], - }, - 7: {}, - 10: { - 662: [ - (3, Some(7)), - ], - }, - 12: {}, - 13: { - 600: [ - (6, None), - ], - }, - 14: { - 601: [ - (15, Some(18)), - ], - }, - 18: { - 627: [ - (15, Some(18)), - ], - }, - }, - 600: { - 5: { - 625: [ - (8, None), - ], - }, - 6: {}, - 7: {}, - 8: {}, - 9: { - 660: [ - (3, Some(4)), - ], - }, - 12: {}, - 18: { - 601: [ - (5, Some(9)), - ], - 635: [ - (1, Some(6)), - ], - }, - }, - 601: { - 0: { - 608: [ - (0, Some(10)), - ], - }, - 1: { - 625: [ - (6, Some(7)), - ], - }, - 4: {}, - 5: { - 650: [ - (14, None), - ], - }, - 6: { - 650: [ - (2, None), - ], - }, - 8: {}, - 12: {}, - 14: {}, - 15: { - 608: [ - (9, Some(13)), - ], - }, - 16: { - 650: [ - (0, Some(15)), - ], - }, - 17: {}, - 18: {}, - 19: {}, - }, - 606: { - 3: { - 619: [ - (8, Some(15)), - ], - }, - 6: {}, - 7: {}, - 16: {}, - 19: { - 662: [ - (6, Some(16)), - ], - }, - }, - 608: { - 4: {}, - 6: { - 635: [ - (5, Some(18)), - ], - }, - 9: {}, - 12: { - 662: [ - (17, None), - ], - }, - 17: {}, - }, - 613: { - 3: {}, - 8: { - 627: [ - (7, Some(15)), - ], - 662: [ - (0, Some(4)), - ], - }, - 10: { - 635: [ - (1, Some(16)), - ], - }, - 16: { - 619: [ - (4, Some(9)), - ], - 635: [ - (14, Some(18)), - ], - }, - }, - 619: { - 1: {}, - 2: { - 625: [ - (6, None), - ], - }, - 4: { - 650: [ - (0, None), - ], - }, - 6: {}, - 8: {}, - 10: {}, - 14: { - 645: [ - (2, None), - ], - 662: [ - (0, Some(8)), - ], - }, - 15: {}, - }, - 625: { - 1: { - 627: [ - (12, Some(19)), - ], - }, - 4: {}, - 6: { - 647: [ - (0, None), - ], - }, - 8: {}, - 10: {}, - }, - 627: { - 1: {}, - 3: {}, - 7: {}, - 11: {}, - 12: {}, - 14: {}, - 15: { - 650: [ - (2, Some(15)), - ], - }, - 17: { - 662: [ - (18, Some(19)), - ], - }, - 18: {}, - 19: { - 635: [ - (4, None), - ], - }, - }, - 635: { - 0: {}, - 1: {}, - 4: { - 660: [ - (0, None), - ], - }, - 5: {}, - 9: {}, - 14: { - 662: [ - (15, Some(19)), - ], - }, - 15: {}, - 17: {}, - 18: {}, - }, - 645: { - 0: {}, - 2: { - 660: [ - (3, None), - ], - }, - 5: {}, - 6: {}, - 16: {}, - 17: {}, - }, - 647: { - 3: {}, - 11: {}, - }, - 650: { - 0: {}, - 2: {}, - 7: {}, - 14: {}, - 16: { - 660: [ - (0, None), - ], - }, - }, - 660: { - 1: {}, - 3: {}, - 9: { - 662: [ - (3, Some(19)), - ], - }, - 15: {}, - }, - 662: { - 2: {}, - 3: {}, - 6: {}, - 7: {}, - 8: {}, - 15: {}, - 16: {}, - 17: {}, - 18: {}, - 19: {}, - }, -} \ No newline at end of file diff --git a/vendor/pubgrub/tests/examples.rs b/vendor/pubgrub/tests/examples.rs deleted file mode 100644 index 9c11d4fef..000000000 --- a/vendor/pubgrub/tests/examples.rs +++ /dev/null @@ -1,211 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use pubgrub::range::Range; -use pubgrub::solver::{resolve, OfflineDependencyProvider}; -use pubgrub::type_aliases::Map; -use pubgrub::version::{NumberVersion, SemanticVersion}; - -type NumVS = Range; -type SemVS = Range; - -use log::LevelFilter; -use std::io::Write; - -fn init_log() { - let _ = env_logger::builder() - .filter_level(LevelFilter::Trace) - .format(|buf, record| writeln!(buf, "{}", record.args())) - .is_test(true) - .try_init(); -} - -#[test] -/// https://github.com/dart-lang/pub/blob/master/doc/solver.md#no-conflicts -fn no_conflict() { - init_log(); - let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new(); - #[rustfmt::skip] - dependency_provider.add_dependencies( - "root", (1, 0, 0), - [("foo", Range::between((1, 0, 0), (2, 0, 0)))], - ); - #[rustfmt::skip] - dependency_provider.add_dependencies( - "foo", (1, 0, 0), - [("bar", Range::between((1, 0, 0), (2, 0, 0)))], - ); - dependency_provider.add_dependencies("bar", (1, 0, 0), []); - dependency_provider.add_dependencies("bar", (2, 0, 0), []); - - // Run the algorithm. - let computed_solution = resolve(&dependency_provider, "root", (1, 0, 0)).unwrap(); - - // Solution. - let mut expected_solution = Map::default(); - expected_solution.insert("root", (1, 0, 0).into()); - expected_solution.insert("foo", (1, 0, 0).into()); - expected_solution.insert("bar", (1, 0, 0).into()); - - // Comparing the true solution with the one computed by the algorithm. - assert_eq!(expected_solution, computed_solution); -} - -#[test] -/// https://github.com/dart-lang/pub/blob/master/doc/solver.md#avoiding-conflict-during-decision-making -fn avoiding_conflict_during_decision_making() { - init_log(); - let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new(); - #[rustfmt::skip] - dependency_provider.add_dependencies( - "root", (1, 0, 0), - [ - ("foo", Range::between((1, 0, 0), (2, 0, 0))), - ("bar", Range::between((1, 0, 0), (2, 0, 0))), - ], - ); - #[rustfmt::skip] - dependency_provider.add_dependencies( - "foo", (1, 1, 0), - [("bar", Range::between((2, 0, 0), (3, 0, 0)))], - ); - dependency_provider.add_dependencies("foo", (1, 0, 0), []); - dependency_provider.add_dependencies("bar", (1, 0, 0), []); - dependency_provider.add_dependencies("bar", (1, 1, 0), []); - dependency_provider.add_dependencies("bar", (2, 0, 0), []); - - // Run the algorithm. - let computed_solution = resolve(&dependency_provider, "root", (1, 0, 0)).unwrap(); - - // Solution. - let mut expected_solution = Map::default(); - expected_solution.insert("root", (1, 0, 0).into()); - expected_solution.insert("foo", (1, 0, 0).into()); - expected_solution.insert("bar", (1, 1, 0).into()); - - // Comparing the true solution with the one computed by the algorithm. - assert_eq!(expected_solution, computed_solution); -} - -#[test] -/// https://github.com/dart-lang/pub/blob/master/doc/solver.md#performing-conflict-resolution -fn conflict_resolution() { - init_log(); - let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new(); - #[rustfmt::skip] - dependency_provider.add_dependencies( - "root", (1, 0, 0), - [("foo", Range::higher_than((1, 0, 0)))], - ); - #[rustfmt::skip] - dependency_provider.add_dependencies( - "foo", (2, 0, 0), - [("bar", Range::between((1, 0, 0), (2, 0, 0)))], - ); - dependency_provider.add_dependencies("foo", (1, 0, 0), []); - #[rustfmt::skip] - dependency_provider.add_dependencies( - "bar", (1, 0, 0), - [("foo", Range::between((1, 0, 0), (2, 0, 0)))], - ); - - // Run the algorithm. - let computed_solution = resolve(&dependency_provider, "root", (1, 0, 0)).unwrap(); - - // Solution. - let mut expected_solution = Map::default(); - expected_solution.insert("root", (1, 0, 0).into()); - expected_solution.insert("foo", (1, 0, 0).into()); - - // Comparing the true solution with the one computed by the algorithm. - assert_eq!(expected_solution, computed_solution); -} - -#[test] -/// https://github.com/dart-lang/pub/blob/master/doc/solver.md#conflict-resolution-with-a-partial-satisfier -fn conflict_with_partial_satisfier() { - init_log(); - let mut dependency_provider = OfflineDependencyProvider::<&str, SemVS>::new(); - #[rustfmt::skip] - // root 1.0.0 depends on foo ^1.0.0 and target ^2.0.0 - dependency_provider.add_dependencies( - "root", (1, 0, 0), - [ - ("foo", Range::between((1, 0, 0), (2, 0, 0))), - ("target", Range::between((2, 0, 0), (3, 0, 0))), - ], - ); - #[rustfmt::skip] - // foo 1.1.0 depends on left ^1.0.0 and right ^1.0.0 - dependency_provider.add_dependencies( - "foo", (1, 1, 0), - [ - ("left", Range::between((1, 0, 0), (2, 0, 0))), - ("right", Range::between((1, 0, 0), (2, 0, 0))), - ], - ); - dependency_provider.add_dependencies("foo", (1, 0, 0), []); - #[rustfmt::skip] - // left 1.0.0 depends on shared >=1.0.0 - dependency_provider.add_dependencies( - "left", (1, 0, 0), - [("shared", Range::higher_than((1, 0, 0)))], - ); - #[rustfmt::skip] - // right 1.0.0 depends on shared <2.0.0 - dependency_provider.add_dependencies( - "right", (1, 0, 0), - [("shared", Range::strictly_lower_than((2, 0, 0)))], - ); - dependency_provider.add_dependencies("shared", (2, 0, 0), []); - #[rustfmt::skip] - // shared 1.0.0 depends on target ^1.0.0 - dependency_provider.add_dependencies( - "shared", (1, 0, 0), - [("target", Range::between((1, 0, 0), (2, 0, 0)))], - ); - dependency_provider.add_dependencies("target", (2, 0, 0), []); - dependency_provider.add_dependencies("target", (1, 0, 0), []); - - // Run the algorithm. - let computed_solution = resolve(&dependency_provider, "root", (1, 0, 0)).unwrap(); - - // Solution. - let mut expected_solution = Map::default(); - expected_solution.insert("root", (1, 0, 0).into()); - expected_solution.insert("foo", (1, 0, 0).into()); - expected_solution.insert("target", (2, 0, 0).into()); - - // Comparing the true solution with the one computed by the algorithm. - assert_eq!(expected_solution, computed_solution); -} - -#[test] -/// a0 dep on b and c -/// b0 dep on d0 -/// b1 dep on d1 (not existing) -/// c0 has no dep -/// c1 dep on d2 (not existing) -/// d0 has no dep -/// -/// Solution: a0, b0, c0, d0 -fn double_choices() { - init_log(); - let mut dependency_provider = OfflineDependencyProvider::<&str, NumVS>::new(); - dependency_provider.add_dependencies("a", 0, [("b", Range::full()), ("c", Range::full())]); - dependency_provider.add_dependencies("b", 0, [("d", Range::singleton(0))]); - dependency_provider.add_dependencies("b", 1, [("d", Range::singleton(1))]); - dependency_provider.add_dependencies("c", 0, []); - dependency_provider.add_dependencies("c", 1, [("d", Range::singleton(2))]); - dependency_provider.add_dependencies("d", 0, []); - - // Solution. - let mut expected_solution = Map::default(); - expected_solution.insert("a", 0.into()); - expected_solution.insert("b", 0.into()); - expected_solution.insert("c", 0.into()); - expected_solution.insert("d", 0.into()); - - // Run the algorithm. - let computed_solution = resolve(&dependency_provider, "a", 0).unwrap(); - assert_eq!(expected_solution, computed_solution); -} diff --git a/vendor/pubgrub/tests/proptest.rs b/vendor/pubgrub/tests/proptest.rs deleted file mode 100644 index 017efed0e..000000000 --- a/vendor/pubgrub/tests/proptest.rs +++ /dev/null @@ -1,619 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use std::{collections::BTreeSet as Set, error::Error}; - -use pubgrub::error::PubGrubError; -use pubgrub::package::Package; -use pubgrub::range::Range; -use pubgrub::report::{DefaultStringReporter, DerivationTree, External, Reporter}; -use pubgrub::solver::{resolve, Dependencies, DependencyProvider, OfflineDependencyProvider}; -use pubgrub::type_aliases::SelectedDependencies; -use pubgrub::version::{NumberVersion, SemanticVersion}; -use pubgrub::version_set::VersionSet; - -use proptest::collection::{btree_map, btree_set, vec}; -use proptest::prelude::*; -use proptest::sample::Index; -use proptest::string::string_regex; - -use crate::sat_dependency_provider::SatResolve; - -mod sat_dependency_provider; - -/// The same as [OfflineDependencyProvider] but takes versions from the opposite end: -/// if [OfflineDependencyProvider] returns versions from newest to oldest, this returns them from oldest to newest. -#[derive(Clone)] -struct OldestVersionsDependencyProvider( - OfflineDependencyProvider, -); - -impl DependencyProvider - for OldestVersionsDependencyProvider -{ - fn get_dependencies( - &self, - p: &P, - v: &VS::V, - ) -> Result, Box> { - self.0.get_dependencies(p, v) - } - - fn choose_version( - &self, - package: &P, - range: &VS, - ) -> Result, Box> { - Ok(self - .0 - .versions(package) - .into_iter() - .flatten() - .find(|&v| range.contains(v)) - .cloned()) - } - - type Priority = as DependencyProvider>::Priority; - - fn prioritize(&self, package: &P, range: &VS) -> Self::Priority { - self.0.prioritize(package, range) - } -} - -/// The same as DP but it has a timeout. -#[derive(Clone)] -struct TimeoutDependencyProvider { - dp: DP, - start_time: std::time::Instant, - call_count: std::cell::Cell, - max_calls: u64, -} - -impl TimeoutDependencyProvider { - fn new(dp: DP, max_calls: u64) -> Self { - Self { - dp, - start_time: std::time::Instant::now(), - call_count: std::cell::Cell::new(0), - max_calls, - } - } -} - -impl> DependencyProvider - for TimeoutDependencyProvider -{ - fn get_dependencies( - &self, - p: &P, - v: &VS::V, - ) -> Result, Box> { - self.dp.get_dependencies(p, v) - } - - fn should_cancel(&self) -> Result<(), Box> { - assert!(self.start_time.elapsed().as_secs() < 60); - let calls = self.call_count.get(); - assert!(calls < self.max_calls); - self.call_count.set(calls + 1); - Ok(()) - } - - fn choose_version( - &self, - package: &P, - range: &VS, - ) -> Result, Box> { - self.dp.choose_version(package, range) - } - - type Priority = DP::Priority; - - fn prioritize(&self, package: &P, range: &VS) -> Self::Priority { - self.dp.prioritize(package, range) - } -} - -fn timeout_resolve>( - dependency_provider: DP, - name: P, - version: impl Into, -) -> Result, PubGrubError> { - resolve( - &TimeoutDependencyProvider::new(dependency_provider, 50_000), - name, - version, - ) -} - -type NumVS = Range; -type SemVS = Range; - -#[test] -#[should_panic] -fn should_cancel_can_panic() { - let mut dependency_provider = OfflineDependencyProvider::<_, NumVS>::new(); - dependency_provider.add_dependencies(0, 0, [(666, Range::full())]); - - // Run the algorithm. - let _ = resolve( - &TimeoutDependencyProvider::new(dependency_provider, 1), - 0, - 0, - ); -} - -fn string_names() -> impl Strategy { - string_regex("[A-Za-z][A-Za-z0-9_-]{0,5}") - .unwrap() - .prop_filter("reserved names", |n| { - // root is the name of the thing being compiled - // so it would be confusing to have it in the index - // bad is a name reserved for a dep that won't work - n != "root" && n != "bad" - }) -} - -/// This generates a random registry index. -/// Unlike vec((Name, Ver, vec((Name, VerRq), ..), ..) -/// This strategy has a high probability of having valid dependencies -pub fn registry_strategy( - name: impl Strategy, -) -> impl Strategy, Vec<(N, NumberVersion)>)> { - let max_crates = 40; - let max_versions = 15; - let shrinkage = 40; - let complicated_len = 10usize; - - let a_version = ..(max_versions as u32); - - let list_of_versions = btree_set(a_version, 1..=max_versions) - .prop_map(move |ver| ver.into_iter().collect::>()); - - let list_of_crates_with_versions = btree_map(name, list_of_versions, 1..=max_crates); - - // each version of each crate can depend on each crate smaller then it. - // In theory shrinkage should be 2, but in practice we get better trees with a larger value. - let max_deps = max_versions * (max_crates * (max_crates - 1)) / shrinkage; - - let raw_version_range = (any::(), any::()); - let raw_dependency = (any::(), any::(), raw_version_range); - - fn order_index(a: Index, b: Index, size: usize) -> (usize, usize) { - use std::cmp::{max, min}; - let (a, b) = (a.index(size), b.index(size)); - (min(a, b), max(a, b)) - } - - let list_of_raw_dependency = vec(raw_dependency, ..=max_deps); - - // By default a package depends only on other packages that have a smaller name, - // this helps make sure that all things in the resulting index are DAGs. - // If this is true then the DAG is maintained with grater instead. - let reverse_alphabetical = any::().no_shrink(); - - ( - list_of_crates_with_versions, - list_of_raw_dependency, - reverse_alphabetical, - 1..(complicated_len + 1), - ) - .prop_map( - move |(crate_vers_by_name, raw_dependencies, reverse_alphabetical, complicated_len)| { - let mut list_of_pkgid: Vec<((N, NumberVersion), Vec<(N, NumVS)>)> = - crate_vers_by_name - .iter() - .flat_map(|(name, vers)| { - vers.iter() - .map(move |x| ((name.clone(), NumberVersion::from(x)), vec![])) - }) - .collect(); - let len_all_pkgid = list_of_pkgid.len(); - for (a, b, (c, d)) in raw_dependencies { - let (a, b) = order_index(a, b, len_all_pkgid); - let (a, b) = if reverse_alphabetical { (b, a) } else { (a, b) }; - let ((dep_name, _), _) = list_of_pkgid[a].to_owned(); - if (list_of_pkgid[b].0).0 == dep_name { - continue; - } - let s = &crate_vers_by_name[&dep_name]; - let s_last_index = s.len() - 1; - let (c, d) = order_index(c, d, s.len() + 1); - - list_of_pkgid[b].1.push(( - dep_name, - if c > s_last_index { - Range::empty() - } else if c == 0 && d >= s_last_index { - Range::full() - } else if c == 0 { - Range::strictly_lower_than(s[d] + 1) - } else if d >= s_last_index { - Range::higher_than(s[c]) - } else if c == d { - Range::singleton(s[c]) - } else { - Range::between(s[c], s[d] + 1) - }, - )); - } - - let mut dependency_provider = OfflineDependencyProvider::::new(); - - let complicated_len = std::cmp::min(complicated_len, list_of_pkgid.len()); - let complicated: Vec<_> = if reverse_alphabetical { - &list_of_pkgid[..complicated_len] - } else { - &list_of_pkgid[(list_of_pkgid.len() - complicated_len)..] - } - .iter() - .map(|(x, _)| (x.0.clone(), x.1)) - .collect(); - - for ((name, ver), deps) in list_of_pkgid { - dependency_provider.add_dependencies(name, ver, deps); - } - - (dependency_provider, complicated) - }, - ) -} - -/// Ensures that generator makes registries with large dependency trees. -#[test] -fn meta_test_deep_trees_from_strategy() { - use proptest::strategy::ValueTree; - use proptest::test_runner::TestRunner; - - let mut dis = [0; 21]; - - let strategy = registry_strategy(0u16..665); - let mut test_runner = TestRunner::deterministic(); - for _ in 0..128 { - let (dependency_provider, cases) = strategy - .new_tree(&mut TestRunner::new_with_rng( - Default::default(), - test_runner.new_rng(), - )) - .unwrap() - .current(); - - for (name, ver) in cases { - let res = resolve(&dependency_provider, name, ver); - dis[res - .as_ref() - .map(|x| std::cmp::min(x.len(), dis.len()) - 1) - .unwrap_or(0)] += 1; - if dis.iter().all(|&x| x > 0) { - return; - } - } - } - - panic!( - "In {} tries we did not see a wide enough distribution of dependency trees! dis: {:?}", - dis.iter().sum::(), - dis - ); -} - -/// Removes versions from the dependency provider where the retain function returns false. -/// Solutions are constructed as a set of versions. -/// If there are fewer versions available, there are fewer valid solutions available. -/// If there was no solution to a resolution in the original dependency provider, -/// then there must still be no solution with some options removed. -/// If there was a solution to a resolution in the original dependency provider, -/// there may not be a solution after versions are removes iif removed versions were critical for all valid solutions. -fn retain_versions( - dependency_provider: &OfflineDependencyProvider, - mut retain: impl FnMut(&N, &VS::V) -> bool, -) -> OfflineDependencyProvider { - let mut smaller_dependency_provider = OfflineDependencyProvider::new(); - - for n in dependency_provider.packages() { - for v in dependency_provider.versions(n).unwrap() { - if !retain(n, v) { - continue; - } - let deps = match dependency_provider.get_dependencies(&n, &v).unwrap() { - Dependencies::Unknown => panic!(), - Dependencies::Known(deps) => deps, - }; - smaller_dependency_provider.add_dependencies(n.clone(), v.clone(), deps) - } - } - smaller_dependency_provider -} - -/// Removes dependencies from the dependency provider where the retain function returns false. -/// Solutions are constraned by having to fulfill all the dependencies. -/// If there are fewer dependencies required, there are more valid solutions. -/// If there was a solution to a resolution in the original dependency provider, -/// then there must still be a solution after dependencies are removed. -/// If there was no solution to a resolution in the original dependency provider, -/// there may now be a solution after dependencies are removed. -fn retain_dependencies( - dependency_provider: &OfflineDependencyProvider, - mut retain: impl FnMut(&N, &VS::V, &N) -> bool, -) -> OfflineDependencyProvider { - let mut smaller_dependency_provider = OfflineDependencyProvider::new(); - for n in dependency_provider.packages() { - for v in dependency_provider.versions(n).unwrap() { - let deps = match dependency_provider.get_dependencies(&n, &v).unwrap() { - Dependencies::Unknown => panic!(), - Dependencies::Known(deps) => deps, - }; - smaller_dependency_provider.add_dependencies( - n.clone(), - v.clone(), - deps.iter().filter_map(|(dep, range)| { - if !retain(n, v, dep) { - None - } else { - Some((dep.clone(), range.clone())) - } - }), - ); - } - } - smaller_dependency_provider -} - -fn errors_the_same_with_only_report_dependencies( - dependency_provider: OfflineDependencyProvider, - name: N, - ver: NumberVersion, -) { - let Err(PubGrubError::NoSolution(tree)) = - timeout_resolve(dependency_provider.clone(), name.clone(), ver) - else { - return; - }; - - fn recursive( - to_retain: &mut Vec<(N, VS, N)>, - tree: &DerivationTree, - ) { - match tree { - DerivationTree::External(External::FromDependencyOf(n1, vs1, n2, _)) => { - to_retain.push((n1.clone(), vs1.clone(), n2.clone())); - } - DerivationTree::Derived(d) => { - recursive(to_retain, &*d.cause1); - recursive(to_retain, &*d.cause2); - } - _ => {} - } - } - - let mut to_retain = Vec::new(); - recursive(&mut to_retain, &tree); - - let removed_provider = retain_dependencies(&dependency_provider, |p, v, d| { - to_retain - .iter() - .any(|(n1, vs1, n2)| n1 == p && vs1.contains(v) && n2 == d) - }); - - assert!( - timeout_resolve(removed_provider.clone(), name, ver).is_err(), - "The full index errored filtering to only dependencies in the derivation tree succeeded" - ); -} - -proptest! { - #![proptest_config(ProptestConfig { - max_shrink_iters: - if std::env::var("CI").is_ok() { - // This attempts to make sure that CI will fail fast, - 0 - } else { - // but that local builds will give a small clear test case. - 2048 - }, - result_cache: prop::test_runner::basic_result_cache, - .. ProptestConfig::default() - })] - - #[test] - /// This test is mostly for profiling. - fn prop_passes_string( - (dependency_provider, cases) in registry_strategy(string_names()) - ) { - for (name, ver) in cases { - _ = timeout_resolve(dependency_provider.clone(), name, ver); - } - } - - #[test] - /// This test is mostly for profiling. - fn prop_passes_int( - (dependency_provider, cases) in registry_strategy(0u16..665) - ) { - for (name, ver) in cases { - _ = timeout_resolve(dependency_provider.clone(), name, ver); - } - } - - #[test] - fn prop_sat_errors_the_same( - (dependency_provider, cases) in registry_strategy(0u16..665) - ) { - let mut sat = SatResolve::new(&dependency_provider); - for (name, ver) in cases { - let res = timeout_resolve(dependency_provider.clone(), name, ver); - sat.check_resolve(&res, &name, &ver); - } - } - - #[test] - fn prop_errors_the_same_with_only_report_dependencies( - (dependency_provider, cases) in registry_strategy(0u16..665) - ) { - for (name, ver) in cases { - errors_the_same_with_only_report_dependencies(dependency_provider.clone(), name, ver); - } - } - - #[test] - /// This tests whether the algorithm is still deterministic. - fn prop_same_on_repeated_runs( - (dependency_provider, cases) in registry_strategy(0u16..665) - ) { - for (name, ver) in cases { - let one = timeout_resolve(dependency_provider.clone(), name, ver); - for _ in 0..3 { - match (&one, &timeout_resolve(dependency_provider.clone(), name, ver)) { - (Ok(l), Ok(r)) => assert_eq!(l, r), - (Err(PubGrubError::NoSolution(derivation_l)), Err(PubGrubError::NoSolution(derivation_r))) => { - prop_assert_eq!( - DefaultStringReporter::report(derivation_l), - DefaultStringReporter::report(derivation_r) - )}, - _ => panic!("not the same result") - } - } - } - } - - #[test] - /// [ReverseDependencyProvider] changes what order the candidates - /// are tried but not the existence of a solution. - fn prop_reversed_version_errors_the_same( - (dependency_provider, cases) in registry_strategy(0u16..665) - ) { - let reverse_provider = OldestVersionsDependencyProvider(dependency_provider.clone()); - for (name, ver) in cases { - let l = timeout_resolve(dependency_provider.clone(), name, ver); - let r = timeout_resolve(reverse_provider.clone(), name, ver); - match (&l, &r) { - (Ok(_), Ok(_)) => (), - (Err(_), Err(_)) => (), - _ => panic!("not the same result") - } - } - } - - #[test] - fn prop_removing_a_dep_cant_break( - (dependency_provider, cases) in registry_strategy(0u16..665), - indexes_to_remove in prop::collection::vec((any::(), any::(), any::()), 1..10) - ) { - let packages: Vec<_> = dependency_provider.packages().collect(); - let mut to_remove = Set::new(); - for (package_idx, version_idx, dep_idx) in indexes_to_remove { - let package = package_idx.get(&packages); - let versions: Vec<_> = dependency_provider - .versions(package) - .unwrap().collect(); - let version = version_idx.get(&versions); - let dependencies: Vec<(u16, NumVS)> = match dependency_provider - .get_dependencies(package, version) - .unwrap() - { - Dependencies::Unknown => panic!(), - Dependencies::Known(d) => d.into_iter().collect(), - }; - if !dependencies.is_empty() { - to_remove.insert((package, **version, dep_idx.get(&dependencies).0)); - } - } - let removed_provider = retain_dependencies( - &dependency_provider, - |p, v, d| {!to_remove.contains(&(&p, *v, *d))} - ); - for (name, ver) in cases { - if timeout_resolve(dependency_provider.clone(), name, ver).is_ok() { - prop_assert!( - timeout_resolve(removed_provider.clone(), name, ver).is_ok(), - "full index worked for `{} = \"={}\"` but removing some deps broke it!", - name, - ver, - ) - } - } - } - - #[test] - fn prop_limited_independence_of_irrelevant_alternatives( - (dependency_provider, cases) in registry_strategy(0u16..665), - indexes_to_remove in prop::collection::vec(any::(), 1..10) - ) { - let all_versions: Vec<(u16, NumberVersion)> = dependency_provider - .packages() - .flat_map(|&p| { - dependency_provider - .versions(&p) - .unwrap() - .map(move |&v| (p, v)) - }) - .collect(); - let to_remove: Set<(_, _)> = indexes_to_remove.iter().map(|x| x.get(&all_versions)).cloned().collect(); - for (name, ver) in cases { - match timeout_resolve(dependency_provider.clone(), name, ver) { - Ok(used) => { - // If resolution was successful, then unpublishing a version of a crate - // that was not selected should not change that. - let smaller_dependency_provider = retain_versions(&dependency_provider, |n, v| { - used.get(&n) == Some(&v) // it was used - || to_remove.get(&(*n, *v)).is_none() // or it is not one to be removed - }); - prop_assert!( - timeout_resolve(smaller_dependency_provider.clone(), name, ver).is_ok(), - "unpublishing {:?} stopped `{} = \"={}\"` from working", - to_remove, - name, - ver - ) - } - Err(_) => { - // If resolution was unsuccessful, then it should stay unsuccessful - // even if any version of a crate is unpublished. - let smaller_dependency_provider = retain_versions(&dependency_provider, |n, v| { - to_remove.get(&(*n, *v)).is_some() // it is one to be removed - }); - prop_assert!( - timeout_resolve(smaller_dependency_provider.clone(), name, ver).is_err(), - "full index did not work for `{} = \"={}\"` but unpublishing {:?} fixed it!", - name, - ver, - to_remove, - ) - } - } - } - } -} - -#[cfg(feature = "serde")] -#[test] -fn large_case() { - for case in std::fs::read_dir("test-examples").unwrap() { - let case = case.unwrap().path(); - let name = case.file_name().unwrap().to_string_lossy(); - eprint!("{} ", name); - let data = std::fs::read_to_string(&case).unwrap(); - let start_time = std::time::Instant::now(); - if name.ends_with("u16_NumberVersion.ron") { - let dependency_provider: OfflineDependencyProvider = - ron::de::from_str(&data).unwrap(); - let mut sat = SatResolve::new(&dependency_provider); - for p in dependency_provider.packages() { - for v in dependency_provider.versions(p).unwrap() { - let res = resolve(&dependency_provider, p.clone(), v); - sat.check_resolve(&res, p, v); - } - } - } else if name.ends_with("str_SemanticVersion.ron") { - let dependency_provider: OfflineDependencyProvider<&str, SemVS> = - ron::de::from_str(&data).unwrap(); - let mut sat = SatResolve::new(&dependency_provider); - for p in dependency_provider.packages() { - for v in dependency_provider.versions(p).unwrap() { - let res = resolve(&dependency_provider, p.clone(), v); - sat.check_resolve(&res, p, v); - } - } - } - eprintln!(" in {}s", start_time.elapsed().as_secs()) - } -} diff --git a/vendor/pubgrub/tests/sat_dependency_provider.rs b/vendor/pubgrub/tests/sat_dependency_provider.rs deleted file mode 100644 index 2bfb21e99..000000000 --- a/vendor/pubgrub/tests/sat_dependency_provider.rs +++ /dev/null @@ -1,151 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use pubgrub::error::PubGrubError; -use pubgrub::package::Package; -use pubgrub::solver::{Dependencies, DependencyProvider, OfflineDependencyProvider}; -use pubgrub::type_aliases::{Map, SelectedDependencies}; -use pubgrub::version_set::VersionSet; -use varisat::ExtendFormula; - -fn sat_at_most_one(solver: &mut impl varisat::ExtendFormula, vars: &[varisat::Var]) { - if vars.len() <= 1 { - return; - } else if vars.len() == 2 { - solver.add_clause(&[vars[0].negative(), vars[1].negative()]); - return; - } else if vars.len() == 3 { - solver.add_clause(&[vars[0].negative(), vars[1].negative()]); - solver.add_clause(&[vars[0].negative(), vars[2].negative()]); - solver.add_clause(&[vars[1].negative(), vars[2].negative()]); - return; - } - // use the "Binary Encoding" from - // https://www.it.uu.se/research/group/astra/ModRef10/papers/Alan%20M.%20Frisch%20and%20Paul%20A.%20Giannoros.%20SAT%20Encodings%20of%20the%20At-Most-k%20Constraint%20-%20ModRef%202010.pdf - let len_bits = vars.len().ilog2() as usize + 1; - let bits: Vec = solver.new_var_iter(len_bits).collect(); - for (i, p) in vars.iter().enumerate() { - for (j, &bit) in bits.iter().enumerate() { - solver.add_clause(&[p.negative(), bit.lit(((1 << j) & i) > 0)]); - } - } -} - -/// Resolution can be reduced to the SAT problem. So this is an alternative implementation -/// of the resolver that uses a SAT library for the hard work. This is intended to be easy to read, -/// as compared to the real resolver. This will find a valid resolution if one exists. -/// -/// The SAT library does not optimize for the newer version, -/// so the selected packages may not match the real resolver. -pub struct SatResolve { - solver: varisat::Solver<'static>, - all_versions_by_p: Map>, -} - -impl SatResolve { - pub fn new(dp: &OfflineDependencyProvider) -> Self { - let mut cnf = varisat::CnfFormula::new(); - - let mut all_versions = vec![]; - let mut all_versions_by_p: Map> = Map::default(); - - for p in dp.packages() { - let mut versions_for_p = vec![]; - for v in dp.versions(p).unwrap() { - let new_var = cnf.new_var(); - all_versions.push((p.clone(), v.clone(), new_var)); - versions_for_p.push(new_var); - all_versions_by_p - .entry(p.clone()) - .or_default() - .push((v.clone(), new_var)); - } - // no two versions of the same package - sat_at_most_one(&mut cnf, &versions_for_p); - } - - // active packages need each of there `deps` to be satisfied - for (p, v, var) in &all_versions { - let deps = match dp.get_dependencies(p, v).unwrap() { - Dependencies::Unknown => panic!(), - Dependencies::Known(d) => d, - }; - for (p1, range) in &deps { - let empty_vec = vec![]; - let mut matches: Vec = all_versions_by_p - .get(p1) - .unwrap_or(&empty_vec) - .iter() - .filter(|(v1, _)| range.contains(v1)) - .map(|(_, var1)| var1.positive()) - .collect(); - // ^ the `dep` is satisfied or - matches.push(var.negative()); - // ^ `p` is not active - cnf.add_clause(&matches); - } - } - - let mut solver = varisat::Solver::new(); - solver.add_formula(&cnf); - - // We dont need to `solve` now. We know that "use nothing" will satisfy all the clauses so far. - // But things run faster if we let it spend some time figuring out how the constraints interact before we add assumptions. - solver - .solve() - .expect("docs say it can't error in default config"); - - Self { - solver, - all_versions_by_p, - } - } - - pub fn resolve(&mut self, name: &P, ver: &VS::V) -> bool { - if let Some(vers) = self.all_versions_by_p.get(name) { - if let Some((_, var)) = vers.iter().find(|(v, _)| v == ver) { - self.solver.assume(&[var.positive()]); - - self.solver - .solve() - .expect("docs say it can't error in default config") - } else { - false - } - } else { - false - } - } - - pub fn is_valid_solution(&mut self, pids: &SelectedDependencies) -> bool { - let mut assumption = vec![]; - - for (p, vs) in &self.all_versions_by_p { - let pid_for_p = pids.get(p); - for (v, var) in vs { - assumption.push(var.lit(pid_for_p == Some(v))) - } - } - - self.solver.assume(&assumption); - - self.solver - .solve() - .expect("docs say it can't error in default config") - } - - pub fn check_resolve( - &mut self, - res: &Result, PubGrubError>, - p: &P, - v: &VS::V, - ) { - match res { - Ok(s) => { - assert!(self.is_valid_solution(s)); - } - Err(_) => { - assert!(!self.resolve(p, v)); - } - } - } -} diff --git a/vendor/pubgrub/tests/tests.rs b/vendor/pubgrub/tests/tests.rs deleted file mode 100644 index 81fd5324c..000000000 --- a/vendor/pubgrub/tests/tests.rs +++ /dev/null @@ -1,56 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -use pubgrub::error::PubGrubError; -use pubgrub::range::Range; -use pubgrub::solver::{resolve, OfflineDependencyProvider}; -use pubgrub::version::NumberVersion; - -type NumVS = Range; - -#[test] -fn same_result_on_repeated_runs() { - let mut dependency_provider = OfflineDependencyProvider::<_, NumVS>::new(); - - dependency_provider.add_dependencies("c", 0, []); - dependency_provider.add_dependencies("c", 2, []); - dependency_provider.add_dependencies("b", 0, []); - dependency_provider.add_dependencies("b", 1, [("c", Range::between(0, 1))]); - - dependency_provider.add_dependencies("a", 0, [("b", Range::full()), ("c", Range::full())]); - - let name = "a"; - let ver = NumberVersion(0); - let one = resolve(&dependency_provider, name, ver); - for _ in 0..10 { - match (&one, &resolve(&dependency_provider, name, ver)) { - (Ok(l), Ok(r)) => assert_eq!(l, r), - _ => panic!("not the same result"), - } - } -} - -#[test] -fn should_always_find_a_satisfier() { - let mut dependency_provider = OfflineDependencyProvider::<_, NumVS>::new(); - dependency_provider.add_dependencies("a", 0, [("b", Range::empty())]); - assert!(matches!( - resolve(&dependency_provider, "a", 0), - Err(PubGrubError::NoSolution { .. }) - )); - - dependency_provider.add_dependencies("c", 0, [("a", Range::full())]); - assert!(matches!( - resolve(&dependency_provider, "c", 0), - Err(PubGrubError::NoSolution { .. }) - )); -} - -#[test] -fn cannot_depend_on_self() { - let mut dependency_provider = OfflineDependencyProvider::<_, NumVS>::new(); - dependency_provider.add_dependencies("a", 0, [("a", Range::full())]); - assert!(matches!( - resolve(&dependency_provider, "a", 0), - Err(PubGrubError::SelfDependency { .. }) - )); -}