Merge "lixexpr: Declutter error traces" into main
This commit is contained in:
+62
-42
@@ -1039,40 +1039,34 @@ void EvalState::eval(Expr & e, Value & v)
|
||||
e.eval(*this, ctx.builtins.env, v);
|
||||
}
|
||||
|
||||
#define checkType(typeName, stringName) \
|
||||
if (v.type() != (typeName)) \
|
||||
ctx.errors.make<TypeError>( \
|
||||
"expected a %1% but found %2%: %3%", \
|
||||
Uncolored(stringName), \
|
||||
showType(v), \
|
||||
ValuePrinter(*this, v, errorPrintOptions) \
|
||||
).atPos(e.getPos()).withFrame(env, e).debugThrow();
|
||||
|
||||
inline bool EvalState::evalBool(Env & env, Expr & e, const PosIdx pos, std::string_view errorCtx)
|
||||
inline bool EvalState::evalBool(Env & env, Expr & e)
|
||||
{
|
||||
try {
|
||||
Value v;
|
||||
e.eval(*this, env, v);
|
||||
if (v.type() != nBool)
|
||||
ctx.errors.make<TypeError>(
|
||||
"expected a Boolean but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
).atPos(pos).withFrame(env, e).debugThrow();
|
||||
return v.boolean;
|
||||
} catch (Error & e) {
|
||||
e.addTrace(ctx.positions[pos], errorCtx);
|
||||
throw;
|
||||
}
|
||||
Value v;
|
||||
e.eval(*this, env, v);
|
||||
checkType(nBool, "Boolean");
|
||||
return v.boolean;
|
||||
}
|
||||
|
||||
|
||||
inline void EvalState::evalAttrs(Env & env, Expr & e, Value & v, const PosIdx pos, std::string_view errorCtx)
|
||||
inline void EvalState::evalAttrs(Env & env, Expr & e, Value & v)
|
||||
{
|
||||
try {
|
||||
e.eval(*this, env, v);
|
||||
if (v.type() != nAttrs)
|
||||
ctx.errors.make<TypeError>(
|
||||
"expected a set but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
).withFrame(env, e).debugThrow();
|
||||
} catch (Error & e) {
|
||||
e.addTrace(ctx.positions[pos], errorCtx);
|
||||
throw;
|
||||
}
|
||||
e.eval(*this, env, v);
|
||||
checkType(nAttrs, "set");
|
||||
}
|
||||
|
||||
inline void EvalState::evalList(Env & env, Expr & e, Value & v)
|
||||
{
|
||||
e.eval(*this, env, v);
|
||||
checkType(nList, "list");
|
||||
}
|
||||
|
||||
|
||||
@@ -1248,7 +1242,19 @@ Value * ExprList::maybeThunk(EvalState & state, Env & env)
|
||||
void ExprVar::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
Value * v2 = state.lookupVar(&env, *this, false);
|
||||
state.forceValue(*v2, pos);
|
||||
try {
|
||||
state.forceValue(*v2, pos);
|
||||
} catch (Error & e) {
|
||||
/* `name` can be invalid if we are an ExprInheritFrom */
|
||||
if (name) {
|
||||
e.addTrace(
|
||||
state.ctx.positions[getPos()],
|
||||
"while evaluating %s",
|
||||
state.ctx.symbols[name]
|
||||
);
|
||||
}
|
||||
throw;
|
||||
}
|
||||
v = *v2;
|
||||
}
|
||||
|
||||
@@ -1848,14 +1854,13 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
void ExprIf::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
// We cheat in the parser, and pass the position of the condition as the position of the if itself.
|
||||
(state.evalBool(env, *cond, pos, "while evaluating a branch condition") ? *then : *else_).eval(state, env, v);
|
||||
(state.evalBool(env, *cond) ? *then : *else_).eval(state, env, v);
|
||||
}
|
||||
|
||||
|
||||
void ExprAssert::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
if (!state.evalBool(env, *cond, pos, "in the condition of the assert statement")) {
|
||||
if (!state.evalBool(env, *cond)) {
|
||||
state.ctx.errors.make<AssertionError>("assertion failed")
|
||||
.atPos(pos)
|
||||
.withFrame(env, *this)
|
||||
@@ -1867,7 +1872,7 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
void ExprOpNot::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
v.mkBool(!state.evalBool(env, *e, getPos(), "in the argument of the not operator")); // XXX: FIXME: !
|
||||
v.mkBool(!state.evalBool(env, *e));
|
||||
}
|
||||
|
||||
|
||||
@@ -1889,27 +1894,27 @@ void ExprOpNEq::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
void ExprOpAnd::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
v.mkBool(state.evalBool(env, *e1, pos, "in the left operand of the AND (&&) operator") && state.evalBool(env, *e2, pos, "in the right operand of the AND (&&) operator"));
|
||||
v.mkBool(state.evalBool(env, *e1) && state.evalBool(env, *e2));
|
||||
}
|
||||
|
||||
|
||||
void ExprOpOr::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
v.mkBool(state.evalBool(env, *e1, pos, "in the left operand of the OR (||) operator") || state.evalBool(env, *e2, pos, "in the right operand of the OR (||) operator"));
|
||||
v.mkBool(state.evalBool(env, *e1) || state.evalBool(env, *e2));
|
||||
}
|
||||
|
||||
|
||||
void ExprOpImpl::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
v.mkBool(!state.evalBool(env, *e1, pos, "in the left operand of the IMPL (->) operator") || state.evalBool(env, *e2, pos, "in the right operand of the IMPL (->) operator"));
|
||||
v.mkBool(!state.evalBool(env, *e1) || state.evalBool(env, *e2));
|
||||
}
|
||||
|
||||
|
||||
void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
Value v1, v2;
|
||||
state.evalAttrs(env, *e1, v1, pos, "in the left operand of the update (//) operator");
|
||||
state.evalAttrs(env, *e2, v2, pos, "in the right operand of the update (//) operator");
|
||||
state.evalAttrs(env, *e1, v1);
|
||||
state.evalAttrs(env, *e2, v2);
|
||||
|
||||
state.ctx.stats.nrOpUpdates++;
|
||||
|
||||
@@ -1945,10 +1950,25 @@ void ExprOpUpdate::eval(EvalState & state, Env & env, Value & v)
|
||||
|
||||
void ExprOpConcatLists::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
Value v1; e1->eval(state, env, v1);
|
||||
Value v2; e2->eval(state, env, v2);
|
||||
Value * lists[2] = { &v1, &v2 };
|
||||
state.concatLists(v, 2, lists, pos, "while evaluating one of the elements to concatenate");
|
||||
state.ctx.stats.nrListConcats++;
|
||||
|
||||
/* We don't call into `concatLists` as that loses the position information of the expressions. */
|
||||
|
||||
Value v1; state.evalList(env, *e1, v1);
|
||||
Value v2; state.evalList(env, *e2, v2);
|
||||
|
||||
size_t l1 = v1.listSize(), l2 = v2.listSize(), len = l1 + l2;
|
||||
|
||||
if (l1 == 0)
|
||||
v = v2;
|
||||
else if (l2 == 0)
|
||||
v = v1;
|
||||
else {
|
||||
v = state.ctx.mem.newList(len);
|
||||
auto out = v.listElems();
|
||||
std::copy(v1.listElems(), v1.listElems() + l1, out);
|
||||
std::copy(v2.listElems(), v2.listElems() + l2, out + l1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -717,8 +717,8 @@ public:
|
||||
* type.
|
||||
*/
|
||||
inline bool evalBool(Env & env, Expr & e);
|
||||
inline bool evalBool(Env & env, Expr & e, const PosIdx pos, std::string_view errorCtx);
|
||||
inline void evalAttrs(Env & env, Expr & e, Value & v, const PosIdx pos, std::string_view errorCtx);
|
||||
inline void evalAttrs(Env & env, Expr & e, Value & v);
|
||||
inline void evalList(Env & env, Expr & e, Value & v);
|
||||
|
||||
/**
|
||||
* If `v` is a thunk, enter it and overwrite `v` with the result
|
||||
|
||||
@@ -1,4 +1,19 @@
|
||||
error: infinite recursion encountered
|
||||
error:
|
||||
… while evaluating x
|
||||
at /pwd/lang/eval-fail-blackhole.nix:5:1:
|
||||
4| in
|
||||
5| x
|
||||
| ^
|
||||
6|
|
||||
|
||||
… while evaluating y
|
||||
at /pwd/lang/eval-fail-blackhole.nix:2:7:
|
||||
1| let
|
||||
2| x = y;
|
||||
| ^
|
||||
3| y = x;
|
||||
|
||||
error: infinite recursion encountered
|
||||
at /pwd/lang/eval-fail-blackhole.nix:2:7:
|
||||
1| let
|
||||
2| x = y;
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
error:
|
||||
… while evaluating one of the elements to concatenate
|
||||
at /pwd/lang/eval-fail-list.nix:1:2:
|
||||
error: expected a list but found an integer: 8
|
||||
at /pwd/lang/eval-fail-list.nix:1:1:
|
||||
1| 8++1
|
||||
| ^
|
||||
| ^
|
||||
2|
|
||||
|
||||
error: expected a list but found an integer: 8
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
error:
|
||||
… in the argument of the not operator
|
||||
at /pwd/lang/eval-fail-not-throws.nix:1:1:
|
||||
1| ! (throw "uh oh!")
|
||||
| ^
|
||||
2|
|
||||
|
||||
… caused by explicit throw
|
||||
at /pwd/lang/eval-fail-not-throws.nix:1:4:
|
||||
1| ! (throw "uh oh!")
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
error:
|
||||
… in the condition of the assert statement
|
||||
at /pwd/lang/eval-fail-print-limit-list.nix:1:1:
|
||||
error: expected a Boolean but found a list: [ 1 [ 2 3 4 5 6 7 8 9 [ 1 «2 items elided» ] «2 items elided» ] «1 item elided» ]
|
||||
at /pwd/lang/eval-fail-print-limit-list.nix:2:3:
|
||||
1| assert (
|
||||
| ^
|
||||
2| let x = [ 1 [ 2 3 4 5 6 7 8 9 x 10 11 ] 12 ];
|
||||
|
||||
error: expected a Boolean but found a list: [ 1 [ 2 3 4 5 6 7 8 9 [ 1 «2 items elided» ] «2 items elided» ] «1 item elided» ]
|
||||
at /pwd/lang/eval-fail-print-limit-list.nix:1:1:
|
||||
1| assert (
|
||||
| ^
|
||||
2| let x = [ 1 [ 2 3 4 5 6 7 8 9 x 10 11 ] 12 ];
|
||||
| ^
|
||||
3| in builtins.deepSeq x x
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
error:
|
||||
… in the condition of the assert statement
|
||||
at /pwd/lang/eval-fail-print-limit-set.nix:1:1:
|
||||
error: expected a Boolean but found a set: { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { ... }; b = 2; }; }; }; }; }; }; }; }; «1 attribute elided» }; «1 attribute elided» }
|
||||
at /pwd/lang/eval-fail-print-limit-set.nix:2:3:
|
||||
1| assert (
|
||||
| ^
|
||||
2| let x = { a.a.a.a.a.a.a.a.a = { a.a = 1; b = 2; }; a.b.c.x = 3; c = 4; };
|
||||
|
||||
error: expected a Boolean but found a set: { a = { a = { a = { a = { a = { a = { a = { a = { a = { a = { ... }; b = 2; }; }; }; }; }; }; }; }; «1 attribute elided» }; «1 attribute elided» }
|
||||
at /pwd/lang/eval-fail-print-limit-set.nix:1:1:
|
||||
1| assert (
|
||||
| ^
|
||||
2| let x = { a.a.a.a.a.a.a.a.a = { a.a = 1; b = 2; }; a.b.c.x = 3; c = 4; };
|
||||
| ^
|
||||
3| in builtins.deepSeq x x
|
||||
|
||||
@@ -5,10 +5,16 @@ error:
|
||||
| ^
|
||||
2|
|
||||
|
||||
… in the right operand of the update (//) operator
|
||||
at /pwd/lang/eval-fail-recursion.nix:1:12:
|
||||
… while evaluating a
|
||||
at /pwd/lang/eval-fail-recursion.nix:1:21:
|
||||
1| let a = {} // a; in a.foo
|
||||
| ^
|
||||
| ^
|
||||
2|
|
||||
|
||||
… while evaluating a
|
||||
at /pwd/lang/eval-fail-recursion.nix:1:15:
|
||||
1| let a = {} // a; in a.foo
|
||||
| ^
|
||||
2|
|
||||
|
||||
error: infinite recursion encountered
|
||||
|
||||
@@ -13,6 +13,20 @@ error:
|
||||
| ^
|
||||
6| in
|
||||
|
||||
… while evaluating x
|
||||
at /pwd/lang/eval-fail-scope-5.nix:5:23:
|
||||
4|
|
||||
5| f = {x ? y, y ? x}: x + y;
|
||||
| ^
|
||||
6| in
|
||||
|
||||
… while evaluating y
|
||||
at /pwd/lang/eval-fail-scope-5.nix:5:12:
|
||||
4|
|
||||
5| f = {x ? y, y ? x}: x + y;
|
||||
| ^
|
||||
6| in
|
||||
|
||||
error: infinite recursion encountered
|
||||
at /pwd/lang/eval-fail-scope-5.nix:5:12:
|
||||
4|
|
||||
|
||||
@@ -20,6 +20,13 @@ We expect to be able to see locals like r in the debugger:
|
||||
error:
|
||||
… while evaluating the file '$TEST_DATA/regression_9918.nix':
|
||||
|
||||
… while evaluating x
|
||||
at $TEST_DATA/regression_9918.nix:5:3:
|
||||
4| in
|
||||
5| x
|
||||
| ^
|
||||
6|
|
||||
|
||||
… while calling the 'throw' builtin
|
||||
at $TEST_DATA/regression_9918.nix:3:7:
|
||||
2| r = [];
|
||||
@@ -27,6 +34,6 @@ We expect to be able to see locals like r in the debugger:
|
||||
| ^
|
||||
4| in
|
||||
|
||||
… while evaluating the error message passed to builtin.throw
|
||||
(stack trace truncated; use '--show-trace' to show the full trace)
|
||||
|
||||
error: cannot coerce a list to a string: [ ]
|
||||
|
||||
@@ -16,6 +16,13 @@ debugger should not crash now, but also not show any with variables
|
||||
error:
|
||||
… while evaluating the file '$TEST_DATA/regression_l145.nix':
|
||||
|
||||
… while evaluating variable x
|
||||
at $TEST_DATA/regression_l145.nix:5:3:
|
||||
4| in
|
||||
5| x
|
||||
| ^
|
||||
6|
|
||||
|
||||
… while calling the 'break' builtin
|
||||
at $TEST_DATA/regression_l145.nix:3:7:
|
||||
2| let
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
@args ${PWD}/extra_data/repl-overlay-fail.nix
|
||||
@should-start false
|
||||
error:
|
||||
… while calling the 'foldl'' builtin
|
||||
at «string»:5:13:
|
||||
4| functions:
|
||||
5| let final = builtins.foldl'
|
||||
| ^
|
||||
6| (prev: function: prev // (function info final prev))
|
||||
… while evaluating variable final
|
||||
at «string»:6:1:
|
||||
5| in
|
||||
6| final
|
||||
| ^
|
||||
7|
|
||||
|
||||
… in the right operand of the update (//) operator
|
||||
at «string»:6:37:
|
||||
5| let final = builtins.foldl'
|
||||
6| (prev: function: prev // (function info final prev))
|
||||
| ^
|
||||
7| initial
|
||||
… while calling the 'foldl'' builtin
|
||||
at «string»:4:11:
|
||||
3| let
|
||||
4| final = builtins.foldl' (prev: function: prev // (function info final prev)) initial functions;
|
||||
| ^
|
||||
5| in
|
||||
|
||||
(stack trace truncated; use '--show-trace' to show the full trace)
|
||||
|
||||
|
||||
@@ -779,10 +779,9 @@ namespace nix {
|
||||
TypeError,
|
||||
HintFmt("attempt to call something which is not a function but %s: %s", "an integer", Uncolored(ANSI_CYAN "1" ANSI_NORMAL)));
|
||||
|
||||
ASSERT_TRACE2("foldl' (a: b: a && b) \"foo\" [ true ]",
|
||||
ASSERT_TRACE1("foldl' (a: b: a && b) \"foo\" [ true ]",
|
||||
TypeError,
|
||||
HintFmt("expected a Boolean but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)),
|
||||
HintFmt("in the left operand of the AND (&&) operator"));
|
||||
HintFmt("expected a Boolean but found %s: %s", "a string", Uncolored(ANSI_MAGENTA "\"foo\"" ANSI_NORMAL)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user