diff options
-rw-r--r-- | doc/manual/rl-next/debugger-on-trace.md | 9 | ||||
-rw-r--r-- | src/libexpr/eval-settings.hh | 10 | ||||
-rw-r--r-- | src/libexpr/primops.cc | 10 |
3 files changed, 29 insertions, 0 deletions
diff --git a/doc/manual/rl-next/debugger-on-trace.md b/doc/manual/rl-next/debugger-on-trace.md new file mode 100644 index 000000000..721928550 --- /dev/null +++ b/doc/manual/rl-next/debugger-on-trace.md @@ -0,0 +1,9 @@ +--- +synopsis: Enter the `--debugger` when `builtins.trace` is called if `debugger-on-trace` is set +prs: 9914 +--- + +If the `debugger-on-trace` option is set and `--debugger` is given, +`builtins.trace` calls will behave similarly to `builtins.break` and will enter +the debug REPL. This is useful for determining where warnings are being emitted +from. diff --git a/src/libexpr/eval-settings.hh b/src/libexpr/eval-settings.hh index 7a92b9728..c78213255 100644 --- a/src/libexpr/eval-settings.hh +++ b/src/libexpr/eval-settings.hh @@ -114,6 +114,16 @@ struct EvalSettings : Config Setting<unsigned int> maxCallDepth{this, 10000, "max-call-depth", "The maximum function call depth to allow before erroring."}; + + Setting<bool> builtinsTraceDebugger{this, false, "debugger-on-trace", + R"( + If set to true and the `--debugger` flag is given, + [`builtins.trace`](@docroot@/language/builtins.md#builtins-trace) will + enter the debugger like + [`builtins.break`](@docroot@/language/builtins.md#builtins-break). + + This is useful for debugging warnings in third-party Nix code. + )"}; }; extern EvalSettings evalSettings; diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 30933e191..b5b28efcd 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -980,6 +980,10 @@ static void prim_trace(EvalState & state, const PosIdx pos, Value * * args, Valu printError("trace: %1%", args[0]->string.s); else printError("trace: %1%", ValuePrinter(state, *args[0])); + if (evalSettings.builtinsTraceDebugger && state.debugRepl && !state.debugTraces.empty()) { + const DebugTrace & last = state.debugTraces.front(); + state.runDebugRepl(nullptr, last.env, last.expr); + } state.forceValue(*args[1], pos); v = *args[1]; } @@ -991,6 +995,12 @@ static RegisterPrimOp primop_trace({ Evaluate *e1* and print its abstract syntax representation on standard error. Then return *e2*. This function is useful for debugging. + + If the + [`debugger-on-trace`](@docroot@/command-ref/conf-file.md#conf-debugger-on-trace) + option is set to `true` and the `--debugger` flag is given, the + interactive debugger will be started when `trace` is called (like + [`break`](@docroot@/language/builtins.md#builtins-break)). )", .fun = prim_trace, }); |