summaryrefslogtreecommitdiff
path: root/apt-pkg/solver3.h
diff options
context:
space:
mode:
authorJulian Andres Klode <jak@debian.org>2025-03-08 22:47:36 +0000
committerJulian Andres Klode <jak@debian.org>2025-03-08 22:47:36 +0000
commit1e7f123ea59d6ae3af74725d4dab846f81d122e8 (patch)
tree58688e139f2e92f4f505ff06ef16231ac6cf4ac3 /apt-pkg/solver3.h
parentb63127f956c7768c75e4b10f8f3ccecd6058066f (diff)
parent3967b75ae4a10d0d79560dfecb8eb210aad4f4f2 (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.h60
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); }
+};