Merge pull request #9917 from 9999years/enter-debugger-more-reliably

Enter debugger more reliably in `let` expressions and function calls

(cherry picked from commit c4ed92fa6f836d3d8eb354a48c37a2f9eeecc3aa)
Change-Id: I16d0cad7e898feecd2399723b92ba8df67222fb4
This commit is contained in:
eldritch horrors 2024-03-08 06:38:10 +01:00
parent 3796811571
commit 3e1be9c530
2 changed files with 53 additions and 3 deletions

View file

@ -0,0 +1,25 @@
---
synopsis: The `--debugger` will start more reliably in `let` expressions and function calls
prs: 9917
issues: 6649
---
Previously, if you attempted to evaluate this file with the debugger:
```nix
let
a = builtins.trace "before inner break" (
builtins.break "hello"
);
b = builtins.trace "before outer break" (
builtins.break a
);
in
b
```
Nix would correctly enter the debugger at `builtins.break a`, but if you asked
it to `:continue`, it would skip over the `builtins.break "hello"` expression
entirely.
Now, Nix will correctly enter the debugger at both breakpoints.

View file

@ -852,20 +852,20 @@ void EvalState::addErrorTrace(Error & e, const PosIdx pos, const char * s, const
e.addTrace(positions[pos], hintfmt(s, s2), frame); e.addTrace(positions[pos], hintfmt(s, s2), frame);
} }
template<typename... Args>
static std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker( static std::unique_ptr<DebugTraceStacker> makeDebugTraceStacker(
EvalState & state, EvalState & state,
Expr & expr, Expr & expr,
Env & env, Env & env,
std::shared_ptr<Pos> && pos, std::shared_ptr<Pos> && pos,
const char * s, const Args & ... formatArgs)
const std::string & s2)
{ {
return std::make_unique<DebugTraceStacker>(state, return std::make_unique<DebugTraceStacker>(state,
DebugTrace { DebugTrace {
.pos = std::move(pos), .pos = std::move(pos),
.expr = expr, .expr = expr,
.env = env, .env = env,
.hint = hintfmt(s, s2), .hint = hintfmt(formatArgs...),
.isError = false .isError = false
}); });
} }
@ -1341,6 +1341,19 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
for (auto & i : attrs->attrs) for (auto & i : attrs->attrs)
env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2); env2.values[displ++] = i.second.e->maybeThunk(state, i.second.inherited ? env : env2);
auto dts = state.debugRepl
? makeDebugTraceStacker(
state,
*this,
env2,
getPos()
? std::make_shared<Pos>(state.positions[getPos()])
: nullptr,
"while evaluating a '%1%' expression",
"let"
)
: nullptr;
body->eval(state, env2, v); body->eval(state, env2, v);
} }
@ -1737,6 +1750,18 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
void ExprCall::eval(EvalState & state, Env & env, Value & v) void ExprCall::eval(EvalState & state, Env & env, Value & v)
{ {
auto dts = state.debugRepl
? makeDebugTraceStacker(
state,
*this,
env,
getPos()
? std::make_shared<Pos>(state.positions[getPos()])
: nullptr,
"while calling a function"
)
: nullptr;
Value vFun; Value vFun;
fun->eval(state, env, vFun); fun->eval(state, env, vFun);