forked from lix-project/lix
Merge pull request #10066 from 9999years/print-all-frames
Do not skip any stack frames when `--show-trace` is given
(cherry picked from commit 0b47783d0a879875d558f0b56e49584f25ceb2d0)
Change-Id: Ia0f18266dbcf97543110110c655c219c7a3e3270
This commit is contained in:
parent
f2e11ddce1
commit
a9b813cc3b
10 changed files with 44 additions and 34 deletions
|
@ -28,15 +28,7 @@ template<class T>
|
||||||
EvalErrorBuilder<T> & EvalErrorBuilder<T>::withTrace(PosIdx pos, const std::string_view text)
|
EvalErrorBuilder<T> & EvalErrorBuilder<T>::withTrace(PosIdx pos, const std::string_view text)
|
||||||
{
|
{
|
||||||
error.err.traces.push_front(
|
error.err.traces.push_front(
|
||||||
Trace{.pos = error.state.positions[pos], .hint = HintFmt(std::string(text)), .frame = false});
|
Trace{.pos = error.state.positions[pos], .hint = HintFmt(std::string(text))});
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T>
|
|
||||||
EvalErrorBuilder<T> & EvalErrorBuilder<T>::withFrameTrace(PosIdx pos, const std::string_view text)
|
|
||||||
{
|
|
||||||
error.err.traces.push_front(
|
|
||||||
Trace{.pos = error.state.positions[pos], .hint = HintFmt(std::string(text)), .frame = true});
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,9 +55,9 @@ EvalErrorBuilder<T> & EvalErrorBuilder<T>::withFrame(const Env & env, const Expr
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
EvalErrorBuilder<T> & EvalErrorBuilder<T>::addTrace(PosIdx pos, HintFmt hint, bool frame)
|
EvalErrorBuilder<T> & EvalErrorBuilder<T>::addTrace(PosIdx pos, HintFmt hint)
|
||||||
{
|
{
|
||||||
error.addTrace(error.state.positions[pos], hint, frame);
|
error.addTrace(error.state.positions[pos], hint);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ public:
|
||||||
|
|
||||||
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> & withFrame(const Env & e, const Expr & ex);
|
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> & withFrame(const Env & e, const Expr & ex);
|
||||||
|
|
||||||
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> & addTrace(PosIdx pos, HintFmt hint, bool frame = false);
|
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> & addTrace(PosIdx pos, HintFmt hint);
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> &
|
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> &
|
||||||
|
|
|
@ -812,14 +812,16 @@ void EvalState::runDebugRepl(const Error * error, const Env & env, const Expr &
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::addErrorTrace(Error & e, const char * s, const std::string & s2) const
|
template<typename... Args>
|
||||||
|
void EvalState::addErrorTrace(Error & e, const Args & ... formatArgs) const
|
||||||
{
|
{
|
||||||
e.addTrace(nullptr, s, s2);
|
e.addTrace(nullptr, HintFmt(formatArgs...));
|
||||||
}
|
}
|
||||||
|
|
||||||
void EvalState::addErrorTrace(Error & e, const PosIdx pos, const char * s, const std::string & s2, bool frame) const
|
template<typename... Args>
|
||||||
|
void EvalState::addErrorTrace(Error & e, const PosIdx pos, const Args & ... formatArgs) const
|
||||||
{
|
{
|
||||||
e.addTrace(positions[pos], HintFmt(s, s2), frame);
|
e.addTrace(positions[pos], HintFmt(formatArgs...));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
|
@ -1606,9 +1608,8 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
||||||
"while calling %s",
|
"while calling %s",
|
||||||
lambda.name
|
lambda.name
|
||||||
? concatStrings("'", symbols[lambda.name], "'")
|
? concatStrings("'", symbols[lambda.name], "'")
|
||||||
: "anonymous lambda",
|
: "anonymous lambda");
|
||||||
true);
|
if (pos) addErrorTrace(e, pos, "from call site");
|
||||||
if (pos) addErrorTrace(e, pos, "from call site%s", "", true);
|
|
||||||
}
|
}
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
|
@ -434,10 +434,12 @@ public:
|
||||||
std::string_view forceString(Value & v, NixStringContext & context, const PosIdx pos, std::string_view errorCtx);
|
std::string_view forceString(Value & v, NixStringContext & context, const PosIdx pos, std::string_view errorCtx);
|
||||||
std::string_view forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx);
|
std::string_view forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx);
|
||||||
|
|
||||||
|
template<typename... Args>
|
||||||
[[gnu::noinline]]
|
[[gnu::noinline]]
|
||||||
void addErrorTrace(Error & e, const char * s, const std::string & s2) const;
|
void addErrorTrace(Error & e, const Args & ... formatArgs) const;
|
||||||
|
template<typename... Args>
|
||||||
[[gnu::noinline]]
|
[[gnu::noinline]]
|
||||||
void addErrorTrace(Error & e, const PosIdx pos, const char * s, const std::string & s2, bool frame = false) const;
|
void addErrorTrace(Error & e, const PosIdx pos, const Args & ... formatArgs) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -805,7 +805,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), true);
|
e.addTrace(nullptr, HintFmt(message));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1069,7 +1069,7 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
|
||||||
e.addTrace(nullptr, HintFmt(
|
e.addTrace(nullptr, HintFmt(
|
||||||
"while evaluating derivation '%s'\n"
|
"while evaluating derivation '%s'\n"
|
||||||
" whose name attribute is located at %s",
|
" whose name attribute is located at %s",
|
||||||
drvName, pos), true);
|
drvName, pos));
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1227,8 +1227,7 @@ drvName, Bindings * attrs, Value & v)
|
||||||
|
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace(state.positions[i->pos],
|
e.addTrace(state.positions[i->pos],
|
||||||
HintFmt("while evaluating attribute '%1%' of derivation '%2%'", key, drvName),
|
HintFmt("while evaluating attribute '%1%' of derivation '%2%'", key, drvName));
|
||||||
true);
|
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,9 +10,9 @@ namespace nix {
|
||||||
|
|
||||||
const std::string nativeSystem = SYSTEM;
|
const std::string nativeSystem = SYSTEM;
|
||||||
|
|
||||||
void BaseError::addTrace(std::shared_ptr<Pos> && e, HintFmt hint, bool frame)
|
void BaseError::addTrace(std::shared_ptr<Pos> && e, HintFmt hint)
|
||||||
{
|
{
|
||||||
err.traces.push_front(Trace { .pos = std::move(e), .hint = hint, .frame = frame });
|
err.traces.push_front(Trace { .pos = std::move(e), .hint = hint });
|
||||||
}
|
}
|
||||||
|
|
||||||
void throwExceptionSelfCheck(){
|
void throwExceptionSelfCheck(){
|
||||||
|
@ -60,8 +60,7 @@ inline bool operator<(const Trace& lhs, const Trace& rhs)
|
||||||
// This formats a freshly formatted hint string and then throws it away, which
|
// 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
|
// 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.
|
// used for trace printing, which is infrequent.
|
||||||
return std::forward_as_tuple(lhs.hint.str(), lhs.frame)
|
return lhs.hint.str() < rhs.hint.str();
|
||||||
< std::forward_as_tuple(rhs.hint.str(), rhs.frame);
|
|
||||||
}
|
}
|
||||||
inline bool operator> (const Trace& lhs, const Trace& rhs) { return rhs < lhs; }
|
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); }
|
||||||
|
@ -372,7 +371,6 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
||||||
// prepended to each element of the trace
|
// prepended to each element of the trace
|
||||||
auto ellipsisIndent = " ";
|
auto ellipsisIndent = " ";
|
||||||
|
|
||||||
bool frameOnly = false;
|
|
||||||
if (!einfo.traces.empty()) {
|
if (!einfo.traces.empty()) {
|
||||||
// Stack traces seen since we last printed a chunk of `duplicate frames
|
// Stack traces seen since we last printed a chunk of `duplicate frames
|
||||||
// omitted`.
|
// omitted`.
|
||||||
|
@ -383,7 +381,6 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
||||||
|
|
||||||
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 (frameOnly && !trace.frame) 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";
|
oss << "\n" << ANSI_WARNING "(stack trace truncated; use '--show-trace' to show the full trace)" ANSI_NORMAL << "\n";
|
||||||
|
@ -399,7 +396,6 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
||||||
printSkippedTracesMaybe(oss, ellipsisIndent, count, skippedTraces, tracesSeen);
|
printSkippedTracesMaybe(oss, ellipsisIndent, count, skippedTraces, tracesSeen);
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
frameOnly = trace.frame;
|
|
||||||
|
|
||||||
printTrace(oss, ellipsisIndent, count, trace);
|
printTrace(oss, ellipsisIndent, count, trace);
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,7 +64,6 @@ void printCodeLines(std::ostream & out,
|
||||||
struct Trace {
|
struct Trace {
|
||||||
std::shared_ptr<Pos> pos;
|
std::shared_ptr<Pos> pos;
|
||||||
HintFmt hint;
|
HintFmt hint;
|
||||||
bool frame;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline bool operator<(const Trace& lhs, const Trace& rhs);
|
inline bool operator<(const Trace& lhs, const Trace& rhs);
|
||||||
|
@ -162,7 +161,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, bool frame = false);
|
void addTrace(std::shared_ptr<Pos> && e, HintFmt hint);
|
||||||
|
|
||||||
bool hasTrace() const { return !err.traces.empty(); }
|
bool hasTrace() const { return !err.traces.empty(); }
|
||||||
|
|
||||||
|
|
|
@ -41,4 +41,11 @@ error:
|
||||||
| ^
|
| ^
|
||||||
5| if n > 0
|
5| if n > 0
|
||||||
|
|
||||||
|
… while calling the 'throw' builtin
|
||||||
|
at /pwd/lang/eval-fail-duplicate-traces.nix:7:10:
|
||||||
|
6| then throwAfter (n - 1)
|
||||||
|
7| else throw "Uh oh!";
|
||||||
|
| ^
|
||||||
|
8| in
|
||||||
|
|
||||||
error: Uh oh!
|
error: Uh oh!
|
||||||
|
|
|
@ -27,4 +27,11 @@ error:
|
||||||
| ^
|
| ^
|
||||||
6|
|
6|
|
||||||
|
|
||||||
|
… while calling the 'throw' builtin
|
||||||
|
at /pwd/lang/eval-fail-foldlStrict-strict-op-application.nix:5:9:
|
||||||
|
4| null
|
||||||
|
5| [ (_: throw "Not the final value, but is still forced!") (_: 23) ]
|
||||||
|
| ^
|
||||||
|
6|
|
||||||
|
|
||||||
error: Not the final value, but is still forced!
|
error: Not the final value, but is still forced!
|
||||||
|
|
|
@ -54,4 +54,11 @@ error:
|
||||||
|
|
||||||
(21 duplicate frames omitted)
|
(21 duplicate frames omitted)
|
||||||
|
|
||||||
|
… while calling the 'throw' builtin
|
||||||
|
at /pwd/lang/eval-fail-mutual-recursion.nix:34:10:
|
||||||
|
33| then throwAfterB true 10
|
||||||
|
34| else throw "Uh oh!";
|
||||||
|
| ^
|
||||||
|
35| in
|
||||||
|
|
||||||
error: Uh oh!
|
error: Uh oh!
|
||||||
|
|
Loading…
Reference in a new issue