diff options
| author | Julian Andres Klode <jak@debian.org> | 2025-03-08 22:47:36 +0000 |
|---|---|---|
| committer | Julian Andres Klode <jak@debian.org> | 2025-03-08 22:47:36 +0000 |
| commit | 1e7f123ea59d6ae3af74725d4dab846f81d122e8 (patch) | |
| tree | 58688e139f2e92f4f505ff06ef16231ac6cf4ac3 /apt-pkg/solver3.h | |
| parent | b63127f956c7768c75e4b10f8f3ccecd6058066f (diff) | |
| parent | 3967b75ae4a10d0d79560dfecb8eb210aad4f4f2 (diff) | |
Merge branch 'solver3' into 'main'
solver3: Verbose error messages and some bugfixes
See merge request apt-team/apt!457
Diffstat (limited to 'apt-pkg/solver3.h')
| -rw-r--r-- | apt-pkg/solver3.h | 60 |
1 files changed, 39 insertions, 21 deletions
diff --git a/apt-pkg/solver3.h b/apt-pkg/solver3.h index 0ad0800ba..9d4a195ec 100644 --- a/apt-pkg/solver3.h +++ b/apt-pkg/solver3.h @@ -84,6 +84,7 @@ class Solver struct Clause; struct Work; struct Solved; + friend struct std::hash<APT::Solver::Var>; // \brief Groups of works, these are ordered. // @@ -246,7 +247,7 @@ class Solver // utilizing the discoverQ above. void Discover(Var var); // \brief Link a clause into the watchers - void RegisterClause(Clause &&clause); + const Clause *RegisterClause(Clause &&clause); // \brief Enqueue dependencies shared by all versions of the package. void RegisterCommonDependencies(pkgCache::PkgIterator Pkg); @@ -290,6 +291,19 @@ class Solver // Print dependency chain std::string WhyStr(Var reason) const; + + /** + * \brief Print a long reason string + * + * Print a reason as to why `rclause` implies `decision` for the variable `var`. + * + * \param var The variable to print the reason for + * \param decision The assumed decision to print the reason for (may be different from actual decision if rclause is specified) + * \param rclause The clause that caused this variable to be marked (or would be marked) + * \param prefix A prefix, for indentation purposes, as this is recursive + * \param seen A set of seen objects such that the output does not repeat itself (not for safety, it is acyclic) + */ + std::string LongWhyStr(Var var, bool decision, const Clause *rclause, std::string prefix, std::unordered_set<Var> &seen) const; }; }; // namespace APT @@ -304,48 +318,44 @@ class Solver */ struct APT::Solver::Var { - uint32_t IsVersion : 1; - uint32_t MapPtr : 31; + uint32_t value; + + explicit constexpr Var(uint32_t value = 0) : value{value} {} + explicit Var(pkgCache::PkgIterator const &Pkg) : value(uint32_t(Pkg.MapPointer()) << 1) {} + explicit Var(pkgCache::VerIterator const &Ver) : value(uint32_t(Ver.MapPointer()) << 1 | 1) {} - Var() : IsVersion(0), MapPtr(0) {} - explicit Var(pkgCache::PkgIterator const &Pkg) : IsVersion(0), MapPtr(Pkg.MapPointer()) {} - explicit Var(pkgCache::VerIterator const &Ver) : IsVersion(1), MapPtr(Ver.MapPointer()) {} + inline constexpr bool isVersion() const { return value & 1; } + inline constexpr uint32_t mapPtr() const { return value >> 1; } // \brief Return the package, if any, otherwise 0. map_pointer<pkgCache::Package> Pkg() const { - return IsVersion ? 0 : map_pointer<pkgCache::Package>{(uint32_t)MapPtr}; + return isVersion() ? 0 : map_pointer<pkgCache::Package>{mapPtr()}; } // \brief Return the version, if any, otherwise 0. map_pointer<pkgCache::Version> Ver() const { - return IsVersion ? map_pointer<pkgCache::Version>{(uint32_t)MapPtr} : 0; + return isVersion() ? map_pointer<pkgCache::Version>{mapPtr()} : 0; } // \brief Return the package iterator if storing a package, or an empty one pkgCache::PkgIterator Pkg(pkgCache &cache) const { - return IsVersion ? pkgCache::PkgIterator() : pkgCache::PkgIterator(cache, cache.PkgP + Pkg()); + return isVersion() ? pkgCache::PkgIterator() : pkgCache::PkgIterator(cache, cache.PkgP + Pkg()); } // \brief Return the version iterator if storing a package, or an empty end. pkgCache::VerIterator Ver(pkgCache &cache) const { - return IsVersion ? pkgCache::VerIterator(cache, cache.VerP + Ver()) : pkgCache::VerIterator(); + return isVersion() ? pkgCache::VerIterator(cache, cache.VerP + Ver()) : pkgCache::VerIterator(); } // \brief Return a package, cast from version if needed pkgCache::PkgIterator CastPkg(pkgCache &cache) const { - assert(MapPtr != 0); - return IsVersion ? Ver(cache).ParentPkg() : Pkg(cache); + return isVersion() ? Ver(cache).ParentPkg() : Pkg(cache); } // \brief Check if there is no reason. - bool empty() const - { - return IsVersion == 0 && MapPtr == 0; - } - bool operator==(Var const other) const - { - return IsVersion == other.IsVersion && MapPtr == other.MapPtr; - } + constexpr bool empty() const { return value == 0; } + constexpr bool operator!=(Var const other) const { return value != other.value; } + constexpr bool operator==(Var const other) const { return value == other.value; } std::string toString(pkgCache &cache) const { @@ -381,7 +391,7 @@ struct APT::Solver::Clause inline Clause(Var reason, Group group, bool optional = false, bool negative = false) : reason(reason), group(group), optional(optional), negative(negative) {} - std::string toString(pkgCache &cache) const; + std::string toString(pkgCache &cache, bool pretty = false) const; }; /** @@ -498,3 +508,11 @@ inline const APT::Solver::State &APT::Solver::operator[](Var r) const { return const_cast<Solver &>(*this)[r]; } + +// Custom specialization of std::hash can be injected in namespace std. +template <> +struct std::hash<APT::Solver::Var> +{ + std::hash<decltype(APT::Solver::Var::value)> hash_value; + std::size_t operator()(const APT::Solver::Var &v) const noexcept { return hash_value(v.value); } +}; |
