libutil: refactor trace types and functions into their own file

Change-Id: I00fba6b382991322a083bedeaf169eb5a86f5aeb
This commit is contained in:
Qyriad
2025-11-06 19:19:36 +01:00
parent 1e386c3780
commit f00d720d83
5 changed files with 111 additions and 104 deletions
+50
View File
@@ -0,0 +1,50 @@
#include "lix/libutil/error-trace.hh"
#include "lix/libutil/error.hh"
#include "lix/libutil/position.hh"
namespace nix {
Trace Trace::fromDrv(std::shared_ptr<Pos> pos, std::string drvName)
{
DrvTrace dt(drvName);
HintFmt h(
"while evaluating derivation '%s'\n"
" whose name attribute is located at %s",
dt.drvName,
*pos
);
return Trace{
.pos = pos,
.hint = h,
.drvTrace = dt,
};
}
Trace Trace::fromDrvAttr(std::shared_ptr<Pos> pos, std::string drvName, std::string attrOfDrv)
{
DrvTrace dt(drvName);
HintFmt h("while evaluating attribute '%s' of derivation '%s'", attrOfDrv, dt.drvName);
return Trace{
.pos = pos,
.hint = h,
.drvTrace = dt,
};
}
std::partial_ordering operator<=>(Trace const & lhs, Trace const & rhs)
{
// If either's position is nullptr, then we compare without dereferencing either.
if (!lhs.pos || !rhs.pos) {
return std::forward_as_tuple(lhs.pos != nullptr, lhs.hint.str())
<=> std::forward_as_tuple(rhs.pos != nullptr, rhs.hint.str());
}
return std::forward_as_tuple(*lhs.pos, lhs.hint.str())
<=> std::forward_as_tuple(*rhs.pos, rhs.hint.str());
}
}
+57
View File
@@ -0,0 +1,57 @@
#pragma once
/**
* @file
*/
#include <compare>
#include <memory>
#include <string>
#include <optional>
#include "lix/libutil/fmt.hh"
namespace nix {
struct Pos;
/** @brief Information for a @ref Trace that encountered a derivation.
*
* This is used for summarizing the derivations involved in an eval error
* at the end of a trace-print.
*/
struct DrvTrace
{
std::string drvName;
// TODO: include more structured information like "element 6 of nativeBuildInputs".
DrvTrace() = delete;
explicit DrvTrace(std::string drvName) : drvName(drvName) {}
friend std::strong_ordering
operator<=>(DrvTrace const & lhs, DrvTrace const & rhs) noexcept = default;
};
struct Trace;
struct Trace
{
std::shared_ptr<Pos> pos;
HintFmt hint;
std::optional<DrvTrace> drvTrace;
/** Construct a Trace and canned format message assuming a derivation's
* position and name.
*/
static Trace fromDrv(std::shared_ptr<Pos> pos, std::string drvName);
/** Construct a Trace and canned format message assuming a derivation's
* position, name, and the attribute of that derivation which caused the
* trace.
*/
static Trace fromDrvAttr(std::shared_ptr<Pos> pos, std::string drvName, std::string attrOfDrv);
friend std::partial_ordering operator<=>(Trace const & lhs, Trace const & rhs);
};
}
+1 -58
View File
@@ -1,6 +1,7 @@
#include "lix/libutil/concepts.hh"
#include "lix/libutil/environment-variables.hh"
#include "lix/libutil/error.hh"
#include "lix/libutil/error-trace.hh"
#include "lix/libutil/logging.hh"
#include "lix/libutil/position.hh"
#include "lix/libutil/terminal.hh"
@@ -41,64 +42,6 @@ std::ostream & operator <<(std::ostream & os, const HintFmt & hf)
return os << hf.str();
}
Trace Trace::fromDrv(std::shared_ptr<Pos> pos, std::string drvName)
{
DrvTrace dt(drvName);
HintFmt h(
"while evaluating derivation '%s'\n"
" whose name attribute is located at %s",
dt.drvName,
*pos
);
return Trace{
.pos = pos,
.hint = h,
.drvTrace = dt,
};
}
Trace Trace::fromDrvAttr(std::shared_ptr<Pos> pos, std::string drvName, std::string attrOfDrv)
{
DrvTrace dt(drvName);
HintFmt h("while evaluating attribute '%s' of derivation '%s'", attrOfDrv, dt.drvName);
return Trace{
.pos = pos,
.hint = h,
.drvTrace = dt,
};
}
/**
* An arbitrarily defined value comparison for the purpose of using traces in the key of a sorted container.
*/
inline bool operator<(const Trace& lhs, const Trace& rhs)
{
// `std::shared_ptr` does not have value semantics for its comparison
// functions, so we need to check for nulls and compare the dereferenced
// values here.
if (lhs.pos != rhs.pos) {
if (!lhs.pos)
return true;
if (!rhs.pos)
return false;
if (*lhs.pos != *rhs.pos)
return *lhs.pos < *rhs.pos;
}
// This formats a freshly formatted hint string and then throws it away, which
// shouldn't be much of a problem because it only runs when pos is equal, and this function is
// used for trace printing, which is infrequent.
return lhs.hint.str() < rhs.hint.str();
}
inline bool operator> (const Trace& lhs, const Trace& rhs) { return rhs < lhs; }
inline bool operator<=(const Trace& lhs, const Trace& rhs) { return !(lhs > rhs); }
inline bool operator>=(const Trace& lhs, const Trace& rhs) { return !(lhs < rhs); }
// print lines of code to the ostream, indicating the error column.
void printCodeLines(std::ostream & out,
const std::string & prefix,
+1 -46
View File
@@ -15,6 +15,7 @@
* See libutil/tests/logging.cc for usage examples.
*/
#include "lix/libutil/error-trace.hh"
#include "lix/libutil/json-fwd.hh"
#include "lix/libutil/suggestions.hh"
#include "lix/libutil/fmt.hh"
@@ -67,52 +68,6 @@ void printCodeLines(std::ostream & out,
const Pos & errPos,
const LinesOfCode & loc);
/** @brief Information for a @ref Trace that encountered a derivation.
*
* This is used for summarizing the derivations involved in an eval error
* at the end of a trace-print.
*/
struct DrvTrace
{
std::string drvName;
// TODO: include more structured information like "element 6 of nativeBuildInputs".
DrvTrace() = delete;
explicit DrvTrace(std::string drvName) : drvName(drvName) {}
friend std::strong_ordering operator<=>(DrvTrace const & lhs, DrvTrace const & rhs) noexcept = default;
};
struct Trace;
// n.b.: std::shared_ptr<Pos> can't be dereferenced in this header,
// because we can't include position.hh without circular includes.
// Yay.
Trace traceFromDrv(std::shared_ptr<Pos> pos, std::string drvName);
struct Trace {
std::shared_ptr<Pos> pos;
HintFmt hint;
std::optional<DrvTrace> drvTrace;
/** Construct a Trace and canned format message assuming a derivation's
* position and name.
*/
static Trace fromDrv(std::shared_ptr<Pos> pos, std::string drvName);
/** Construct a Trace and canned format message assuming a derivation's
* position, name, and the attribute of that derivation which caused the
* trace.
*/
static Trace fromDrvAttr(std::shared_ptr<Pos> pos, std::string drvName, std::string attrOfDrv);
};
inline bool operator<(const Trace& lhs, const Trace& rhs);
inline bool operator> (const Trace& lhs, const Trace& rhs);
inline bool operator<=(const Trace& lhs, const Trace& rhs);
inline bool operator>=(const Trace& lhs, const Trace& rhs);
struct ErrorInfo {
Verbosity level = Verbosity::lvlError;
HintFmt msg;
+2
View File
@@ -13,6 +13,7 @@ libutil_sources = files(
'deprecated-features.cc',
'english.cc',
'environment-variables.cc',
'error-trace.cc',
'error.cc',
'escape-char.cc',
'escape-string.cc',
@@ -85,6 +86,7 @@ libutil_headers = files(
'deprecated-features.hh',
'english.hh',
'environment-variables.hh',
'error-trace.hh',
'error.hh',
'escape-char.hh',
'escape-string.hh',