Always print addErrorContext traces

This commit is contained in:
Robert Hensing 2024-03-23 23:56:05 +01:00
parent 38ba96d7b0
commit bebacc475c
7 changed files with 90 additions and 17 deletions

View file

@ -826,7 +826,7 @@ static void prim_addErrorContext(EvalState & state, const PosIdx pos, Value * *
auto message = state.coerceToString(pos, *args[0], context, auto message = state.coerceToString(pos, *args[0], context,
"while evaluating the error message passed to builtins.addErrorContext", "while evaluating the error message passed to builtins.addErrorContext",
false, false).toOwned(); false, false).toOwned();
e.addTrace(nullptr, HintFmt(message)); e.addTrace(nullptr, HintFmt(message), TraceKind::Custom);
throw; throw;
} }
} }

View file

@ -11,9 +11,9 @@
namespace nix { namespace nix {
void BaseError::addTrace(std::shared_ptr<Pos> && e, HintFmt hint) void BaseError::addTrace(std::shared_ptr<Pos> && e, HintFmt hint, TraceKind kind)
{ {
err.traces.push_front(Trace { .pos = std::move(e), .hint = hint }); err.traces.push_front(Trace { .pos = std::move(e), .hint = hint, .kind = kind });
} }
void throwExceptionSelfCheck(){ void throwExceptionSelfCheck(){
@ -379,19 +379,22 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
// A consecutive sequence of stack traces that are all in `tracesSeen`. // A consecutive sequence of stack traces that are all in `tracesSeen`.
std::vector<Trace> skippedTraces; std::vector<Trace> skippedTraces;
size_t count = 0; size_t count = 0;
bool truncate = false;
for (const auto & trace : einfo.traces) { for (const auto & trace : einfo.traces) {
if (trace.hint.str().empty()) continue; if (trace.hint.str().empty()) continue;
if (!showTrace && count > 3) { if (!showTrace && count > 3) {
oss << "\n" << ANSI_WARNING "(stack trace truncated; use '--show-trace' to show the full trace)" ANSI_NORMAL << "\n"; truncate = true;
break;
} }
if (!truncate || trace.kind == TraceKind::Custom) {
if (tracesSeen.count(trace)) { if (tracesSeen.count(trace)) {
skippedTraces.push_back(trace); skippedTraces.push_back(trace);
continue; continue;
} }
tracesSeen.insert(trace); tracesSeen.insert(trace);
printSkippedTracesMaybe(oss, ellipsisIndent, count, skippedTraces, tracesSeen); printSkippedTracesMaybe(oss, ellipsisIndent, count, skippedTraces, tracesSeen);
@ -400,8 +403,15 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
printTrace(oss, ellipsisIndent, count, trace); printTrace(oss, ellipsisIndent, count, trace);
} }
}
printSkippedTracesMaybe(oss, ellipsisIndent, count, skippedTraces, tracesSeen); printSkippedTracesMaybe(oss, ellipsisIndent, count, skippedTraces, tracesSeen);
if (truncate) {
oss << "\n" << ANSI_WARNING "(stack trace truncated; use '--show-trace' to show the full, detailed trace)" ANSI_NORMAL << "\n";
}
oss << "\n" << prefix; oss << "\n" << prefix;
} }

View file

@ -61,9 +61,16 @@ void printCodeLines(std::ostream & out,
const Pos & errPos, const Pos & errPos,
const LinesOfCode & loc); const LinesOfCode & loc);
enum struct TraceKind {
Other,
/** Produced by builtins.addErrorContext. Always printed. */
Custom,
};
struct Trace { struct Trace {
std::shared_ptr<Pos> pos; std::shared_ptr<Pos> pos;
HintFmt hint; HintFmt hint;
TraceKind kind = TraceKind::Other;
}; };
inline bool operator<(const Trace& lhs, const Trace& rhs); inline bool operator<(const Trace& lhs, const Trace& rhs);
@ -161,7 +168,7 @@ public:
addTrace(std::move(e), HintFmt(std::string(fs), args...)); addTrace(std::move(e), HintFmt(std::string(fs), args...));
} }
void addTrace(std::shared_ptr<Pos> && e, HintFmt hint); void addTrace(std::shared_ptr<Pos> && e, HintFmt hint, TraceKind kind = TraceKind::Other);
bool hasTrace() const { return !err.traces.empty(); } bool hasTrace() const { return !err.traces.empty(); }

View file

@ -68,8 +68,16 @@ done
for i in lang/eval-fail-*.nix; do for i in lang/eval-fail-*.nix; do
echo "evaluating $i (should fail)"; echo "evaluating $i (should fail)";
i=$(basename "$i" .nix) i=$(basename "$i" .nix)
flags="$(
if [[ -e "lang/$i.flags" ]]; then
sed -e 's/#.*//' < "lang/$i.flags"
else
# note that show-trace is also set by init.sh
echo "--eval --strict --show-trace"
fi
)"
if if
expectStderr 1 nix-instantiate --eval --strict --show-trace "lang/$i.nix" \ expectStderr 1 nix-instantiate $flags "lang/$i.nix" \
| sed "s!$(pwd)!/pwd!g" > "lang/$i.err" | sed "s!$(pwd)!/pwd!g" > "lang/$i.err"
then then
diffAndAccept "$i" err err.exp diffAndAccept "$i" err err.exp

View file

@ -0,0 +1,38 @@
error:
… while calling the 'addErrorContext' builtin
at /pwd/lang/eval-fail-addErrorContext-example.nix:6:7:
5| else
6| builtins.addErrorContext
| ^
7| "while counting down; n = ${toString n}"
… while counting down; n = 10
… while calling the 'addErrorContext' builtin
at /pwd/lang/eval-fail-addErrorContext-example.nix:6:7:
5| else
6| builtins.addErrorContext
| ^
7| "while counting down; n = ${toString n}"
… while counting down; n = 9
… while counting down; n = 8
… while counting down; n = 7
… while counting down; n = 6
… while counting down; n = 5
… while counting down; n = 4
… while counting down; n = 3
… while counting down; n = 2
… while counting down; n = 1
(stack trace truncated; use '--show-trace' to show the full, detailed trace)
error: kaboom

View file

@ -0,0 +1 @@
--eval --strict --no-show-trace

View file

@ -0,0 +1,9 @@
let
countDown = n:
if n == 0
then throw "kaboom"
else
builtins.addErrorContext
"while counting down; n = ${toString n}"
("x" + countDown (n - 1));
in countDown 10