libexpr: associate positions with EvalContext

Change-Id: I43e827a9119324c23a6d72cfc1b7ed4d5ff32dd2
This commit is contained in:
eldritch horrors 2024-12-03 20:38:41 +01:00
parent 014845ddf1
commit 2f2bc90d92
8 changed files with 65 additions and 65 deletions

View file

@ -797,7 +797,7 @@ void EvalState::evalLazily(Expr & e, Value & v)
void EvalState::mkPos(Value & v, PosIdx p)
{
auto origin = positions.originOf(p);
auto origin = ctx.positions.originOf(p);
if (auto path = std::get_if<SourcePath>(&origin)) {
auto attrs = buildBindings(3);
attrs.alloc(ctx.s.file).mkString(path->path.abs());
@ -961,7 +961,7 @@ void EvalState::evalFile(const SourcePath & path_, Value & v)
*this,
e,
this->builtins.env,
e.getPos() ? std::make_shared<Pos>(positions[e.getPos()]) : nullptr,
e.getPos() ? std::make_shared<Pos>(ctx.positions[e.getPos()]) : nullptr,
"while evaluating the file '%1%':", resolvedPath.to_string())
: nullptr;
@ -1002,7 +1002,7 @@ inline bool EvalState::evalBool(Env & env, Expr & e, const PosIdx pos, std::stri
).atPos(pos).withFrame(env, e).debugThrow();
return v.boolean;
} catch (Error & e) {
e.addTrace(positions[pos], errorCtx);
e.addTrace(ctx.positions[pos], errorCtx);
throw;
}
}
@ -1019,7 +1019,7 @@ inline void EvalState::evalAttrs(Env & env, Expr & e, Value & v, const PosIdx po
ValuePrinter(*this, v, errorPrintOptions)
).withFrame(env, e).debugThrow();
} catch (Error & e) {
e.addTrace(positions[pos], errorCtx);
e.addTrace(ctx.positions[pos], errorCtx);
throw;
}
}
@ -1146,7 +1146,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
auto nameSym = state.ctx.symbols.create(nameVal.string.s);
Bindings::iterator j = v.attrs->find(nameSym);
if (j != v.attrs->end())
state.errors.make<EvalError>("dynamic attribute '%1%' already defined at %2%", state.ctx.symbols[nameSym], state.positions[j->pos]).atPos(i.pos).withFrame(env, *this).debugThrow();
state.errors.make<EvalError>("dynamic attribute '%1%' already defined at %2%", state.ctx.symbols[nameSym], state.ctx.positions[j->pos]).atPos(i.pos).withFrame(env, *this).debugThrow();
i.valueExpr->setName(nameSym);
/* Keep sorted order so find can catch duplicates */
@ -1183,7 +1183,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
*this,
env2,
getPos()
? std::make_shared<Pos>(state.positions[getPos()])
? std::make_shared<Pos>(state.ctx.positions[getPos()])
: nullptr,
"while evaluating a '%1%' expression",
"let"
@ -1252,7 +1252,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
} catch (Error & e) {
assert(this->e != nullptr);
e.addTrace(
state.positions[getPos()],
state.ctx.positions[getPos()],
"while evaluating '%s' to select '%s' on it",
ExprPrinter(state, *this->e),
showAttrPath(state.ctx.symbols, this->attrPath)
@ -1266,7 +1266,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
state,
*this,
env,
state.positions[getPos()],
state.ctx.positions[getPos()],
"while evaluating the attribute '%1%'",
showAttrPath(state, env, attrPath))
: nullptr;
@ -1303,7 +1303,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
state.forceValue(*vCurrent, pos);
} catch (Error & e) {
e.addTrace(
state.positions[getPos()],
state.ctx.positions[getPos()],
"while evaluating '%s' to select '%s' on it",
partsSoFar(),
state.ctx.symbols[name]
@ -1365,7 +1365,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
state.forceValue(*vCurrent, (posCurrent ? posCurrent : this->pos));
} catch (Error & e) {
auto pos2r = state.positions[posCurrent];
auto pos2r = state.ctx.positions[posCurrent];
if (pos2r && !std::get_if<Pos::Hidden>(&pos2r.origin))
e.addTrace(pos2r, "while evaluating the attribute '%1%'",
showAttrPath(state, env, attrPath));
@ -1488,7 +1488,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
CallDepth _level(callDepth);
auto trace = evalSettings.traceFunctionCalls
? std::make_unique<FunctionCallTrace>(positions[pos])
? std::make_unique<FunctionCallTrace>(ctx.positions[pos])
: nullptr;
forceValue(fun, pos);
@ -1527,7 +1527,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
try {
forceAttrs(*args[0], lambda.pos, "while evaluating the value passed for the lambda argument");
} catch (Error & e) {
if (pos) e.addTrace(positions[pos], "from call site");
if (pos) e.addTrace(ctx.positions[pos], "from call site");
throw;
}
@ -1577,7 +1577,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
try {
auto dts = debug
? makeDebugTraceStacker(
*this, *lambda.body, env2, positions[lambda.pos],
*this, *lambda.body, env2, ctx.positions[lambda.pos],
"while calling %s",
lambda.getQuotedName(ctx.symbols))
: nullptr;
@ -1586,10 +1586,10 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
} catch (Error & e) {
if (loggerSettings.showTrace.get()) {
e.addTrace(
positions[lambda.pos],
ctx.positions[lambda.pos],
"while calling %s",
lambda.getQuotedName(ctx.symbols));
if (pos) e.addTrace(positions[pos], "from call site");
if (pos) e.addTrace(ctx.positions[pos], "from call site");
}
throw;
}
@ -1619,13 +1619,13 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
// Distinguish between an error that simply happened while "throw"
// was being evaluated and an explicit thrown error.
if (fn->name == "throw") {
e.addTrace(positions[pos], "caused by explicit %s", "throw");
e.addTrace(ctx.positions[pos], "caused by explicit %s", "throw");
} else {
e.addTrace(positions[pos], "while calling the '%s' builtin", fn->name);
e.addTrace(ctx.positions[pos], "while calling the '%s' builtin", fn->name);
}
throw;
} catch (Error & e) {
e.addTrace(positions[pos], "while calling the '%1%' builtin", fn->name);
e.addTrace(ctx.positions[pos], "while calling the '%1%' builtin", fn->name);
throw;
}
@ -1674,7 +1674,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
// so the debugger allows to inspect the wrong parameters passed to the builtin.
fn->fun(*this, vCur.determinePos(noPos), vArgs.data(), vCur);
} catch (Error & e) {
e.addTrace(positions[pos], "while calling the '%1%' builtin", fn->name);
e.addTrace(ctx.positions[pos], "while calling the '%1%' builtin", fn->name);
throw;
}
@ -1692,7 +1692,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
try {
callFunction(*functor->value, 2, args2, vCur, functor->pos);
} catch (Error & e) {
e.addTrace(positions[pos], "while calling a functor (an attribute set with a '__functor' attribute)");
e.addTrace(ctx.positions[pos], "while calling a functor (an attribute set with a '__functor' attribute)");
throw;
}
nrArgs--;
@ -1720,7 +1720,7 @@ void ExprCall::eval(EvalState & state, Env & env, Value & v)
*this,
env,
getPos()
? std::make_shared<Pos>(state.positions[getPos()])
? std::make_shared<Pos>(state.ctx.positions[getPos()])
: nullptr,
"while calling a function"
)
@ -2066,7 +2066,7 @@ void EvalState::tryFixupBlackHolePos(Value & v, PosIdx pos)
try {
std::rethrow_exception(e);
} catch (InfiniteRecursionError & e) {
e.atPos(positions[pos]);
e.atPos(ctx.positions[pos]);
} catch (...) {
}
}
@ -2088,13 +2088,13 @@ void EvalState::forceValueDeep(Value & v)
try {
// If the value is a thunk, we're evaling. Otherwise no trace necessary.
auto dts = debug && i.value->isThunk()
? makeDebugTraceStacker(*this, *i.value->thunk.expr, *i.value->thunk.env, positions[i.pos],
? makeDebugTraceStacker(*this, *i.value->thunk.expr, *i.value->thunk.env, ctx.positions[i.pos],
"while evaluating the attribute '%1%'", ctx.symbols[i.name])
: nullptr;
recurse(*i.value);
} catch (Error & e) {
e.addTrace(positions[i.pos], "while evaluating the attribute '%1%'", ctx.symbols[i.name]);
e.addTrace(ctx.positions[i.pos], "while evaluating the attribute '%1%'", ctx.symbols[i.name]);
throw;
}
}
@ -2121,7 +2121,7 @@ NixInt EvalState::forceInt(Value & v, const PosIdx pos, std::string_view errorCt
).atPos(pos).debugThrow();
return v.integer;
} catch (Error & e) {
e.addTrace(positions[pos], errorCtx);
e.addTrace(ctx.positions[pos], errorCtx);
throw;
}
@ -2143,7 +2143,7 @@ NixFloat EvalState::forceFloat(Value & v, const PosIdx pos, std::string_view err
).atPos(pos).debugThrow();
return v.fpoint;
} catch (Error & e) {
e.addTrace(positions[pos], errorCtx);
e.addTrace(ctx.positions[pos], errorCtx);
throw;
}
}
@ -2161,7 +2161,7 @@ bool EvalState::forceBool(Value & v, const PosIdx pos, std::string_view errorCtx
).atPos(pos).debugThrow();
return v.boolean;
} catch (Error & e) {
e.addTrace(positions[pos], errorCtx);
e.addTrace(ctx.positions[pos], errorCtx);
throw;
}
@ -2186,7 +2186,7 @@ void EvalState::forceFunction(Value & v, const PosIdx pos, std::string_view erro
ValuePrinter(*this, v, errorPrintOptions)
).atPos(pos).debugThrow();
} catch (Error & e) {
e.addTrace(positions[pos], errorCtx);
e.addTrace(ctx.positions[pos], errorCtx);
throw;
}
}
@ -2204,7 +2204,7 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string
).atPos(pos).debugThrow();
return v.string.s;
} catch (Error & e) {
e.addTrace(positions[pos], errorCtx);
e.addTrace(ctx.positions[pos], errorCtx);
throw;
}
}
@ -2333,7 +2333,7 @@ BackedStringView EvalState::coerceToString(
"while evaluating one element of the list",
coerceMore, copyToStore, canonicalizePath);
} catch (Error & e) {
e.addTrace(positions[pos], errorCtx);
e.addTrace(ctx.positions[pos], errorCtx);
throw;
}
if (n < v.listSize() - 1

View file

@ -88,7 +88,7 @@ static void expectType(EvalState & state, ValueType type,
forceTrivialValue(state, value, pos);
if (value.type() != type)
throw Error("expected %s but got %s at %s",
showType(type), showType(value.type()), state.positions[pos]);
showType(type), showType(value.type()), state.ctx.positions[pos]);
}
static std::map<FlakeId, FlakeInput> parseFlakeInputs(
@ -156,7 +156,7 @@ static FlakeInput parseFlakeInput(EvalState & state,
}
} catch (Error & e) {
e.addTrace(
state.positions[attr.pos],
state.ctx.positions[attr.pos],
HintFmt("while evaluating flake attribute '%s'", state.ctx.symbols[attr.name]));
throw;
}
@ -166,13 +166,13 @@ static FlakeInput parseFlakeInput(EvalState & state,
try {
input.ref = FlakeRef::fromAttrs(attrs);
} catch (Error & e) {
e.addTrace(state.positions[pos], HintFmt("while evaluating flake input"));
e.addTrace(state.ctx.positions[pos], HintFmt("while evaluating flake input"));
throw;
}
else {
attrs.erase("url");
if (!attrs.empty())
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, state.positions[pos]);
throw Error("unexpected flake input attribute '%s', at %s", attrs.begin()->first, state.ctx.positions[pos]);
if (url)
input.ref = parseFlakeRef(*url, baseDir, true, input.isFlake);
}
@ -325,7 +325,7 @@ static Flake getFlake(
attr.name != state.ctx.s.outputs &&
attr.name != sNixConfig)
throw Error("flake '%s' has an unsupported attribute '%s', at %s",
lockedRef, state.ctx.symbols[attr.name], state.positions[attr.pos]);
lockedRef, state.ctx.symbols[attr.name], state.ctx.positions[attr.pos]);
}
return flake;
@ -808,7 +808,7 @@ void prim_getFlake(EvalState & state, const PosIdx pos, Value * * args, Value &
std::string flakeRefS(state.forceStringNoCtx(*args[0], pos, "while evaluating the argument passed to builtins.getFlake"));
auto flakeRef = parseFlakeRef(flakeRefS, {}, true);
if (evalSettings.pureEval && !flakeRef.input.isLocked())
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.positions[pos]);
throw Error("cannot call 'getFlake' on unlocked flake reference '%s', at %s (use --impure to override)", flakeRefS, state.ctx.positions[pos]);
callFlake(state,
lockFlake(state, flakeRef,

View file

@ -619,7 +619,7 @@ std::string ExprLambda::showNamePos(const EvalState & state) const
std::string id(name
? concatStrings("'", state.ctx.symbols[name], "'")
: "anonymous function");
return fmt("%1% at %2%", id, state.positions[pos]);
return fmt("%1% at %2%", id, state.ctx.positions[pos]);
}

View file

@ -137,7 +137,7 @@ static SourcePath realisePath(EvalState & state, const PosIdx pos, Value & v, co
? state.paths.checkSourcePath(realPath)
: realPath;
} catch (Error & e) {
e.addTrace(state.positions[pos], "while realising the context of path '%s'", path);
e.addTrace(state.ctx.positions[pos], "while realising the context of path '%s'", path);
throw;
}
}
@ -325,7 +325,7 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
try {
auto _ = state.paths.realiseContext(context); // FIXME: Handle CA derivations
} catch (InvalidPathError & e) {
e.addTrace(state.positions[pos], "while realising the context for builtins.exec");
e.addTrace(state.ctx.positions[pos], "while realising the context for builtins.exec");
throw;
}
@ -334,13 +334,13 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
try {
parsed = &state.parseExprFromString(std::move(output), CanonPath::root);
} catch (Error & e) {
e.addTrace(state.positions[pos], "while parsing the output from '%1%'", program);
e.addTrace(state.ctx.positions[pos], "while parsing the output from '%1%'", program);
throw;
}
try {
state.eval(*parsed, v);
} catch (Error & e) {
e.addTrace(state.positions[pos], "while evaluating the output from '%1%'", program);
e.addTrace(state.ctx.positions[pos], "while evaluating the output from '%1%'", program);
throw;
}
}
@ -576,7 +576,7 @@ static void prim_break(EvalState & state, const PosIdx pos, Value * * args, Valu
auto error = EvalError(ErrorInfo {
.level = lvlInfo,
.msg = HintFmt("breakpoint reached"),
.pos = state.positions[pos],
.pos = state.ctx.positions[pos],
});
state.debug->onEvalError(&error, (*trace)->env, (*trace)->expr);
@ -747,14 +747,14 @@ static void prim_derivationStrict(EvalState & state, const PosIdx pos, Value * *
try {
drvName = state.forceStringNoCtx(*nameAttr->value, pos, "while evaluating the `name` attribute passed to builtins.derivationStrict");
} catch (Error & e) {
e.addTrace(state.positions[nameAttr->pos], "while evaluating the derivation attribute 'name'");
e.addTrace(state.ctx.positions[nameAttr->pos], "while evaluating the derivation attribute 'name'");
throw;
}
try {
derivationStrictInternal(state, drvName, attrs, v);
} catch (Error & e) {
Pos pos = state.positions[nameAttr->pos];
Pos pos = state.ctx.positions[nameAttr->pos];
/*
* Here we make two abuses of the error system
*
@ -946,7 +946,7 @@ drvName, Bindings * attrs, Value & v)
}
} catch (Error & e) {
e.addTrace(state.positions[i->pos],
e.addTrace(state.ctx.positions[i->pos],
HintFmt("while evaluating attribute '%1%' of derivation '%2%'", key, drvName));
throw;
}
@ -1443,7 +1443,7 @@ static void prim_fromJSON(EvalState & state, const PosIdx pos, Value * * args, V
try {
parseJSON(state, s, v);
} catch (JSONParseError &e) {
e.addTrace(state.positions[pos], "while decoding a JSON string");
e.addTrace(state.ctx.positions[pos], "while decoding a JSON string");
throw;
}
}
@ -1557,7 +1557,7 @@ static void addPath(
} else
state.paths.allowAndSetStorePathString(*expectedStorePath, v);
} catch (Error & e) {
e.addTrace(state.positions[pos], "while adding path '%s'", path);
e.addTrace(state.ctx.positions[pos], "while adding path '%s'", path);
throw;
}
}
@ -1710,13 +1710,13 @@ static struct LazyPosAcessors {
PrimOp primop_lineOfPos{
.arity = 1,
.fun = [] (EvalState & state, PosIdx pos, Value * * args, Value & v) {
v.mkInt(state.positions[PosIdx(args[0]->integer.value)].line);
v.mkInt(state.ctx.positions[PosIdx(args[0]->integer.value)].line);
}
};
PrimOp primop_columnOfPos{
.arity = 1,
.fun = [] (EvalState & state, PosIdx pos, Value * * args, Value & v) {
v.mkInt(state.positions[PosIdx(args[0]->integer.value)].column);
v.mkInt(state.ctx.positions[PosIdx(args[0]->integer.value)].column);
}
};

View file

@ -27,7 +27,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor
state.store->printStorePath(fromPath),
state.store->printStorePath(rewrittenPath),
state.store->printStorePath(*toPathMaybe)),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
if (!toPathMaybe)
throw Error({
@ -36,7 +36,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor
"Use this value for the 'toPath' attribute passed to 'fetchClosure'",
state.store->printStorePath(fromPath),
state.store->printStorePath(rewrittenPath)),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
}
@ -54,7 +54,7 @@ static void runFetchClosureWithRewrite(EvalState & state, const PosIdx pos, Stor
"The 'toPath' value '%s' is input-addressed, so it can't possibly be the result of rewriting to a content-addressed path.\n\n"
"Set 'toPath' to an empty string to make Lix report the correct content-addressed path.",
state.store->printStorePath(toPath)),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
}
@ -80,7 +80,7 @@ static void runFetchClosureWithContentAddressedPath(EvalState & state, const Pos
"to the 'fetchClosure' arguments.\n\n"
"Note that to ensure authenticity input-addressed store paths, users must configure a trusted binary cache public key on their systems. This is not needed for content-addressed paths.",
state.store->printStorePath(fromPath)),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
}
@ -103,7 +103,7 @@ static void runFetchClosureWithInputAddressedPath(EvalState & state, const PosId
"The store object referred to by 'fromPath' at '%s' is not input-addressed, but 'inputAddressed' is set to 'true'.\n\n"
"Remove the 'inputAddressed' attribute (it defaults to 'false') to expect 'fromPath' to be content-addressed",
state.store->printStorePath(fromPath)),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
}
@ -154,14 +154,14 @@ void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * args, Valu
else
throw Error({
.msg = HintFmt("attribute '%s' isn't supported in call to 'fetchClosure'", attrName),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
}
if (!fromPath)
throw Error({
.msg = HintFmt("attribute '%s' is missing in call to 'fetchClosure'", "fromPath"),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
bool inputAddressed = inputAddressedMaybe.value_or(false);
@ -172,14 +172,14 @@ void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * args, Valu
.msg = HintFmt("attribute '%s' is set to true, but '%s' is also set. Please remove one of them",
"inputAddressed",
"toPath"),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
}
if (!fromStoreUrl)
throw Error({
.msg = HintFmt("attribute '%s' is missing in call to 'fetchClosure'", "fromStore"),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
auto parsedURL = parseURL(*fromStoreUrl);
@ -189,13 +189,13 @@ void prim_fetchClosure(EvalState & state, const PosIdx pos, Value * * args, Valu
!(getEnv("_NIX_IN_TEST").has_value() && parsedURL.scheme == "file"))
throw Error({
.msg = HintFmt("'fetchClosure' only supports http:// and https:// stores"),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
if (!parsedURL.query.empty())
throw Error({
.msg = HintFmt("'fetchClosure' does not support URL query parameters (in '%s')", *fromStoreUrl),
.pos = state.positions[pos]
.pos = state.ctx.positions[pos]
});
auto fromStore = openStore(parsedURL.to_string());

View file

@ -400,7 +400,7 @@ private:
}
std::ostringstream s;
s << state.positions[v.lambda.fun->pos];
s << state.ctx.positions[v.lambda.fun->pos];
output << " @ " << filterANSIEscapes(s.str());
}
} else if (v.isPrimOp()) {

View file

@ -63,7 +63,7 @@ json printValueAsJSON(EvalState & state, bool strict,
try {
out[j] = printValueAsJSON(state, strict, *a.value, a.pos, context, copyToStore);
} catch (Error & e) {
e.addTrace(state.positions[a.pos],
e.addTrace(state.ctx.positions[a.pos],
HintFmt("while evaluating attribute '%1%'", j));
throw;
}
@ -80,7 +80,7 @@ json printValueAsJSON(EvalState & state, bool strict,
try {
out.push_back(printValueAsJSON(state, strict, *elem, pos, context, copyToStore));
} catch (Error & e) {
e.addTrace(state.positions[pos],
e.addTrace(state.ctx.positions[pos],
HintFmt("while evaluating list element at index %1%", i));
throw;
}

View file

@ -41,7 +41,7 @@ static void showAttrs(EvalState & state, bool strict, bool location,
XMLAttrs xmlAttrs;
xmlAttrs["name"] = i;
if (location && a.pos) posToXML(state, xmlAttrs, state.positions[a.pos]);
if (location && a.pos) posToXML(state, xmlAttrs, state.ctx.positions[a.pos]);
XMLOpenElement _(doc, "attr", xmlAttrs);
printValueAsXML(state, strict, location,
@ -132,7 +132,7 @@ static void printValueAsXML(EvalState & state, bool strict, bool location,
break;
}
XMLAttrs xmlAttrs;
if (location) posToXML(state, xmlAttrs, state.positions[v.lambda.fun->pos]);
if (location) posToXML(state, xmlAttrs, state.ctx.positions[v.lambda.fun->pos]);
XMLOpenElement _(doc, "function", xmlAttrs);
if (v.lambda.fun->hasFormals()) {