aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/manual/rl-next/better-attrpath-errors.md64
-rw-r--r--src/libexpr/eval.cc15
-rw-r--r--tests/functional/lang/eval-fail-recursion.err.exp6
3 files changed, 84 insertions, 1 deletions
diff --git a/doc/manual/rl-next/better-attrpath-errors.md b/doc/manual/rl-next/better-attrpath-errors.md
new file mode 100644
index 000000000..d06bfc43b
--- /dev/null
+++ b/doc/manual/rl-next/better-attrpath-errors.md
@@ -0,0 +1,64 @@
+---
+synopsis: "Trace when the `foo` part of a `foo.bar.baz` expression errors"
+cls: 1505
+credits: Qyriad
+category: Improvements
+---
+
+Previously, if an expression like `linux_4_9.meta.description` errored in the `linux_4_9` part, it wouldn't show you that that's the part of the expression that failed to evaluate, or even that that line of code is what caused evaluation of the failing expression.
+The previous error looks like this:
+
+```
+let
+ inherit (pkgs.linuxKernel.kernels) linux_4_9;
+in linux_4_9.meta.description
+
+error:
+ … while evaluating the attribute 'linux_4_9'
+ at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:5:
+ 277| } // lib.optionalAttrs config.allowAliases {
+ 278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
+ | ^
+ 279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
+
+ … while calling the 'throw' builtin
+ at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:17:
+ 277| } // lib.optionalAttrs config.allowAliases {
+ 278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
+ | ^
+ 279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
+
+ error: linux 4.9 was removed because it will reach its end of life within 22.11
+```
+
+Now, the error will look like this:
+
+```
+let
+ inherit (pkgs.linuxKernel.kernels) linux_4_9;
+in linux_4_9.meta.description
+error:
+ … while evaluating 'linux_4_9' to select 'meta.description' on it
+ at «string»:3:4:
+ 2| inherit (pkgs.linuxKernel.kernels) linux_4_9;
+ 3| in linux_4_9.meta.description
+ | ^
+
+ … while evaluating the attribute 'linux_4_9'
+ at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:5:
+ 277| } // lib.optionalAttrs config.allowAliases {
+ 278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
+ | ^
+ 279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
+
+ … caused by explicit throw
+ at /nix/store/dk2rpyb6ndvfbf19bkb2plcz5y3k8i5v-source/pkgs/top-level/linux-kernels.nix:278:17:
+ 277| } // lib.optionalAttrs config.allowAliases {
+ 278| linux_4_9 = throw "linux 4.9 was removed because it will reach its end of life within 22.11";
+ | ^
+ 279| linux_4_14 = throw "linux 4.14 was removed because it will reach its end of life within 23.11";
+
+ error: linux 4.9 was removed because it will reach its end of life within 22.11
+```
+
+Not only does the line of code that referenced the failing binding show up in the trace, it also tells you that it was specifically the `linux_4_9` part that failed.
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index a6a64a43c..b01867a09 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -1432,7 +1432,20 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
Value * vCurrent = &vFirst;
// Position for the current attrset Value in this select chain.
PosIdx posCurrent;
- e->eval(state, env, vFirst);
+
+ try {
+ e->eval(state, env, vFirst);
+ } catch (Error & e) {
+ assert(this->e != nullptr);
+ state.addErrorTrace(
+ e,
+ getPos(),
+ "while evaluating '%s' to select '%s' on it",
+ ExprPrinter(state, *this->e),
+ showAttrPath(state.symbols, this->attrPath)
+ );
+ throw;
+ }
try {
auto dts = state.debugRepl
diff --git a/tests/functional/lang/eval-fail-recursion.err.exp b/tests/functional/lang/eval-fail-recursion.err.exp
index 19380dc65..f0057b2d5 100644
--- a/tests/functional/lang/eval-fail-recursion.err.exp
+++ b/tests/functional/lang/eval-fail-recursion.err.exp
@@ -1,4 +1,10 @@
error:
+ … while evaluating 'a' to select 'foo' on it
+ at /pwd/lang/eval-fail-recursion.nix:1:21:
+ 1| let a = {} // a; in a.foo
+ | ^
+ 2|
+
… in the right operand of the update (//) operator
at /pwd/lang/eval-fail-recursion.nix:1:12:
1| let a = {} // a; in a.foo