libexpr: associate error creation and debugging with EvalContext

Change-Id: I80beedd0c58361ebc67cebcee97d64879baed050
This commit is contained in:
eldritch horrors 2024-12-03 20:38:41 +01:00
parent 2f2bc90d92
commit d30027a37a
12 changed files with 142 additions and 142 deletions

View file

@ -56,7 +56,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
if (!attrIndex) {
if (v->type() != nAttrs)
state.errors.make<TypeError>(
state.ctx.errors.make<TypeError>(
"the expression selected by the selection path '%1%' should be a set but is %2%",
attrPath,
showType(*v)).debugThrow();
@ -79,7 +79,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
else {
if (!v->isList())
state.errors.make<TypeError>(
state.ctx.errors.make<TypeError>(
"the expression selected by the selection path '%1%' should be a list but is %2%",
attrPath,
showType(*v)).debugThrow();

View file

@ -552,14 +552,14 @@ std::string AttrCursor::getString(EvalState & state)
debug("using cached string attribute '%s'", getAttrPathStr(state));
return s->first;
} else
state.errors.make<TypeError>("'%s' is not a string", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not a string", getAttrPathStr(state)).debugThrow();
}
}
auto & v = forceValue(state);
if (v.type() != nString && v.type() != nPath) {
state.errors.make<TypeError>("'%s' is not a string but %s", getAttrPathStr(state), v.type()).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not a string but %s", getAttrPathStr(state), v.type()).debugThrow();
}
return v.type() == nString ? v.string.s : v.path().to_string();
@ -595,7 +595,7 @@ string_t AttrCursor::getStringWithContext(EvalState & state)
return *s;
}
} else
state.errors.make<TypeError>("'%s' is not a string", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not a string", getAttrPathStr(state)).debugThrow();
}
}
@ -608,7 +608,7 @@ string_t AttrCursor::getStringWithContext(EvalState & state)
} else if (v.type() == nPath) {
return {v.path().to_string(), {}};
} else {
state.errors.make<TypeError>("'%s' is not a string but %s", getAttrPathStr(state), v.type()).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not a string but %s", getAttrPathStr(state), v.type()).debugThrow();
}
}
@ -622,14 +622,14 @@ bool AttrCursor::getBool(EvalState & state)
debug("using cached Boolean attribute '%s'", getAttrPathStr(state));
return *b;
} else
state.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr(state)).debugThrow();
}
}
auto & v = forceValue(state);
if (v.type() != nBool)
state.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr(state)).debugThrow();
return v.boolean;
}
@ -644,14 +644,14 @@ NixInt AttrCursor::getInt(EvalState & state)
debug("using cached integer attribute '%s'", getAttrPathStr(state));
return i->x;
} else
state.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr(state)).debugThrow();
}
}
auto & v = forceValue(state);
if (v.type() != nInt)
state.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr(state)).debugThrow();
return v.integer;
}
@ -666,7 +666,7 @@ std::vector<std::string> AttrCursor::getListOfStrings(EvalState & state)
debug("using cached list of strings attribute '%s'", getAttrPathStr(state));
return *l;
} else
state.errors.make<TypeError>("'%s' is not a list of strings", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not a list of strings", getAttrPathStr(state)).debugThrow();
}
}
@ -676,7 +676,7 @@ std::vector<std::string> AttrCursor::getListOfStrings(EvalState & state)
state.forceValue(v, noPos);
if (v.type() != nList)
state.errors.make<TypeError>("'%s' is not a list", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not a list", getAttrPathStr(state)).debugThrow();
std::vector<std::string> res;
@ -699,14 +699,14 @@ std::vector<std::string> AttrCursor::getAttrs(EvalState & state)
debug("using cached attrset attribute '%s'", getAttrPathStr(state));
return attrs->p;
} else
state.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr(state)).debugThrow();
}
}
auto & v = forceValue(state);
if (v.type() != nAttrs)
state.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr(state)).debugThrow();
state.ctx.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr(state)).debugThrow();
fullattr_t attrs;
for (auto & attr : *getValue(state).attrs)

View file

@ -91,7 +91,7 @@ inline void EvalState::forceAttrs(Value & v, const PosIdx pos, std::string_view
{
forceValue(v, pos);
if (v.type() != nAttrs) {
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected a set but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -105,7 +105,7 @@ inline void EvalState::forceList(Value & v, const PosIdx pos, std::string_view e
{
forceValue(v, pos);
if (!v.isList()) {
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected a list but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)

View file

@ -618,7 +618,7 @@ void printEnvBindings(const SymbolTable & st, const StaticEnv & se, const Env &
void printEnvBindings(const EvalState &es, const Expr & expr, const Env & env)
{
// just print the names for now
auto se = es.debug->staticEnvFor(expr);
auto se = es.ctx.debug->staticEnvFor(expr);
if (se)
printEnvBindings(es.ctx.symbols, *se, env, 0);
}
@ -739,15 +739,15 @@ static DebugState::TraceFrame makeDebugTraceStacker(
std::shared_ptr<Pos> && pos,
const Args & ... formatArgs)
{
auto trace = state.debug->addTrace(DebugTrace{
auto trace = state.ctx.debug->addTrace(DebugTrace{
.pos = std::move(pos),
.expr = expr,
.env = env,
.hint = HintFmt(formatArgs...),
.isError = false,
});
if (state.debug->stop && state.debug->errorCallback)
state.debug->onEvalError(nullptr, env, expr);
if (state.ctx.debug->stop && state.ctx.debug->errorCallback)
state.ctx.debug->onEvalError(nullptr, env, expr);
return trace;
}
@ -771,7 +771,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
return j->value;
}
if (!fromWith->parentWith)
errors.make<UndefinedVarError>("undefined variable '%1%'", ctx.symbols[var.name]).atPos(var.pos).withFrame(*env, var).debugThrow();
ctx.errors.make<UndefinedVarError>("undefined variable '%1%'", ctx.symbols[var.name]).atPos(var.pos).withFrame(*env, var).debugThrow();
for (size_t l = fromWith->prevWith; l; --l, env = env->up) ;
fromWith = fromWith->parentWith;
}
@ -956,7 +956,7 @@ void EvalState::evalFile(const SourcePath & path_, Value & v)
Expr & e = parseExprFromFile(paths.checkSourcePath(resolvedPath));
try {
auto dts = debug
auto dts = ctx.debug
? makeDebugTraceStacker(
*this,
e,
@ -995,7 +995,7 @@ inline bool EvalState::evalBool(Env & env, Expr & e, const PosIdx pos, std::stri
Value v;
e.eval(*this, env, v);
if (v.type() != nBool)
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected a Boolean but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -1013,7 +1013,7 @@ inline void EvalState::evalAttrs(Env & env, Expr & e, Value & v, const PosIdx po
try {
e.eval(*this, env, v);
if (v.type() != nAttrs)
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected a set but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -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.ctx.positions[j->pos]).atPos(i.pos).withFrame(env, *this).debugThrow();
state.ctx.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 */
@ -1177,7 +1177,7 @@ void ExprLet::eval(EvalState & state, Env & env, Value & v)
*i.second.chooseByKind(&env2, &env, inheritEnv));
}
auto dts = state.debug
auto dts = state.ctx.debug
? makeDebugTraceStacker(
state,
*this,
@ -1261,7 +1261,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
}
try {
auto dts = state.debug
auto dts = state.ctx.debug
? makeDebugTraceStacker(
state,
*this,
@ -1321,7 +1321,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
}
// Otherwise, we must type error.
state.errors.make<TypeError>(
state.ctx.errors.make<TypeError>(
"expected a set but found %s: %s",
showType(*vCurrent),
ValuePrinter(state, *vCurrent, errorPrintOptions)
@ -1348,7 +1348,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
allAttrNames.insert(state.ctx.symbols[attr.name]);
}
auto suggestions = Suggestions::bestMatches(allAttrNames, state.ctx.symbols[name]);
state.errors.make<EvalError>("attribute '%s' missing", state.ctx.symbols[name])
state.ctx.errors.make<EvalError>("attribute '%s' missing", state.ctx.symbols[name])
.atPos(pos)
.withSuggestions(suggestions)
.withFrame(env, *this)
@ -1484,7 +1484,7 @@ FormalsMatch matchupFormals(EvalState & state, Env & env, Displacement & displ,
void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value & vRes, const PosIdx pos)
{
if (callDepth > evalSettings.maxCallDepth)
errors.make<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
ctx.errors.make<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
CallDepth _level(callDepth);
auto trace = evalSettings.traceFunctionCalls
@ -1546,7 +1546,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
);
for (auto const & missingArg : formalsMatch.missing) {
auto const missing = ctx.symbols[missingArg];
errors.make<TypeError>("function '%s' called without required argument '%s'", lambda.getName(ctx.symbols), missing)
ctx.errors.make<TypeError>("function '%s' called without required argument '%s'", lambda.getName(ctx.symbols), missing)
.atPos(lambda.pos)
.withTrace(pos, "from call site")
.withFrame(*fun.lambda.env, lambda)
@ -1559,7 +1559,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
formalNames.insert(ctx.symbols[formal.name]);
}
auto sug = Suggestions::bestMatches(formalNames, unex);
errors.make<TypeError>("function '%s' called with unexpected argument '%s'", lambda.getName(ctx.symbols), unex)
ctx.errors.make<TypeError>("function '%s' called with unexpected argument '%s'", lambda.getName(ctx.symbols), unex)
.atPos(lambda.pos)
.withTrace(pos, "from call site")
.withSuggestions(sug)
@ -1575,7 +1575,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
/* Evaluate the body. */
try {
auto dts = debug
auto dts = ctx.debug
? makeDebugTraceStacker(
*this, *lambda.body, env2, ctx.positions[lambda.pos],
"while calling %s",
@ -1700,7 +1700,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
}
else
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"attempt to call something which is not a function but %1%: %2%",
showType(vCur),
ValuePrinter(*this, vCur, errorPrintOptions))
@ -1714,7 +1714,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
void ExprCall::eval(EvalState & state, Env & env, Value & v)
{
auto dts = state.debug
auto dts = state.ctx.debug
? makeDebugTraceStacker(
state,
*this,
@ -1787,7 +1787,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
if (j != args.end()) {
attrs.insert(*j);
} else if (!i.def) {
errors.make<MissingArgumentError>(R"(cannot evaluate a function that has an argument without a value ('%1%')
ctx.errors.make<MissingArgumentError>(R"(cannot evaluate a function that has an argument without a value ('%1%')
Nix attempted to evaluate a function as a top level expression; in
this case it must have its arguments supplied either by default
values, or passed explicitly with '--arg' or '--argstr'. See
@ -1823,7 +1823,7 @@ void ExprAssert::eval(EvalState & state, Env & env, Value & v)
if (!state.evalBool(env, *cond, pos, "in the condition of the assert statement")) {
std::ostringstream out;
cond->show(state.ctx.symbols, out);
state.errors.make<AssertionError>("assertion '%1%' failed", out.str()).atPos(pos).withFrame(env, *this).debugThrow();
state.ctx.errors.make<AssertionError>("assertion '%1%' failed", out.str()).atPos(pos).withFrame(env, *this).debugThrow();
}
body->eval(state, env, v);
}
@ -1998,7 +1998,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
if (auto checked = newN.valueChecked(); checked.has_value()) {
n = NixInt(*checked);
} else {
state.errors.make<EvalError>("integer overflow in adding %1% + %2%", n, vTmp.integer).atPos(i_pos).debugThrow();
state.ctx.errors.make<EvalError>("integer overflow in adding %1% + %2%", n, vTmp.integer).atPos(i_pos).debugThrow();
}
} else if (vTmp.type() == nFloat) {
// Upgrade the type from int to float;
@ -2006,14 +2006,14 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
nf = n.value;
nf += vTmp.fpoint;
} else
state.errors.make<EvalError>("cannot add %1% to an integer", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow();
state.ctx.errors.make<EvalError>("cannot add %1% to an integer", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow();
} else if (firstType == nFloat) {
if (vTmp.type() == nInt) {
nf += vTmp.integer.value;
} else if (vTmp.type() == nFloat) {
nf += vTmp.fpoint;
} else
state.errors.make<EvalError>("cannot add %1% to a float", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow();
state.ctx.errors.make<EvalError>("cannot add %1% to a float", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow();
} else {
if (s.empty()) s.reserve(es.size());
/* skip canonization of first path, which would only be not
@ -2035,7 +2035,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
v.mkFloat(nf);
else if (firstType == nPath) {
if (!context.empty())
state.errors.make<EvalError>("a string that refers to a store path cannot be appended to a path").atPos(pos).withFrame(env, *this).debugThrow();
state.ctx.errors.make<EvalError>("a string that refers to a store path cannot be appended to a path").atPos(pos).withFrame(env, *this).debugThrow();
v.mkPath(CanonPath(canonPath(str())));
} else
v.mkStringMove(c_str(), context);
@ -2050,7 +2050,7 @@ void ExprPos::eval(EvalState & state, Env & env, Value & v)
void ExprBlackHole::eval(EvalState & state, Env & env, Value & v)
{
state.errors.make<InfiniteRecursionError>("infinite recursion encountered")
state.ctx.errors.make<InfiniteRecursionError>("infinite recursion encountered")
.atPos(v.determinePos(noPos))
.debugThrow();
}
@ -2087,7 +2087,7 @@ void EvalState::forceValueDeep(Value & v)
for (auto & i : *v.attrs)
try {
// If the value is a thunk, we're evaling. Otherwise no trace necessary.
auto dts = debug && i.value->isThunk()
auto dts = ctx.debug && i.value->isThunk()
? makeDebugTraceStacker(*this, *i.value->thunk.expr, *i.value->thunk.env, ctx.positions[i.pos],
"while evaluating the attribute '%1%'", ctx.symbols[i.name])
: nullptr;
@ -2114,7 +2114,7 @@ NixInt EvalState::forceInt(Value & v, const PosIdx pos, std::string_view errorCt
try {
forceValue(v, pos);
if (v.type() != nInt)
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected an integer but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -2136,7 +2136,7 @@ NixFloat EvalState::forceFloat(Value & v, const PosIdx pos, std::string_view err
if (v.type() == nInt)
return v.integer.value;
else if (v.type() != nFloat)
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected a float but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -2154,7 +2154,7 @@ bool EvalState::forceBool(Value & v, const PosIdx pos, std::string_view errorCtx
try {
forceValue(v, pos);
if (v.type() != nBool)
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected a Boolean but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -2180,7 +2180,7 @@ void EvalState::forceFunction(Value & v, const PosIdx pos, std::string_view erro
try {
forceValue(v, pos);
if (v.type() != nFunction && !isFunctor(v))
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected a function but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -2197,7 +2197,7 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string
try {
forceValue(v, pos);
if (v.type() != nString)
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"expected a string but found %1%: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -2230,7 +2230,7 @@ std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos, std::s
{
auto s = forceString(v, pos, errorCtx);
if (v.string.context) {
errors.make<EvalError>("the string '%1%' is not allowed to refer to a store path (such as '%2%')", v.string.s, v.string.context[0]).withTrace(pos, errorCtx).debugThrow();
ctx.errors.make<EvalError>("the string '%1%' is not allowed to refer to a store path (such as '%2%')", v.string.s, v.string.context[0]).withTrace(pos, errorCtx).debugThrow();
}
return s;
}
@ -2295,7 +2295,7 @@ BackedStringView EvalState::coerceToString(
return std::move(*maybeString);
auto i = v.attrs->find(ctx.s.outPath);
if (i == v.attrs->end()) {
errors.make<TypeError>(
ctx.errors.make<TypeError>(
"cannot coerce %1% to a string: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
@ -2345,7 +2345,7 @@ BackedStringView EvalState::coerceToString(
}
}
errors.make<TypeError>("cannot coerce %1% to a string: %2%",
ctx.errors.make<TypeError>("cannot coerce %1% to a string: %2%",
showType(v),
ValuePrinter(*this, v, errorPrintOptions)
)
@ -2382,7 +2382,7 @@ SourcePath EvalState::coerceToPath(const PosIdx pos, Value & v, NixStringContext
{
auto path = coerceToString(pos, v, context, errorCtx, false, false, true).toOwned();
if (path == "" || path[0] != '/')
errors.make<EvalError>("string '%1%' doesn't represent an absolute path", path).withTrace(pos, errorCtx).debugThrow();
ctx.errors.make<EvalError>("string '%1%' doesn't represent an absolute path", path).withTrace(pos, errorCtx).debugThrow();
return CanonPath(path);
}
@ -2392,7 +2392,7 @@ StorePath EvalState::coerceToStorePath(const PosIdx pos, Value & v, NixStringCon
auto path = coerceToString(pos, v, context, errorCtx, false, false, true).toOwned();
if (auto storePath = store->maybeParseStorePath(path))
return *storePath;
errors.make<EvalError>("path '%1%' is not in the Nix store", path).withTrace(pos, errorCtx).debugThrow();
ctx.errors.make<EvalError>("path '%1%' is not in the Nix store", path).withTrace(pos, errorCtx).debugThrow();
}
@ -2402,7 +2402,7 @@ std::pair<SingleDerivedPath, std::string_view> EvalState::coerceToSingleDerivedP
auto s = forceString(v, context, pos, errorCtx);
auto csize = context.size();
if (csize != 1)
errors.make<EvalError>(
ctx.errors.make<EvalError>(
"string '%s' has %d entries in its context. It should only have exactly one entry",
s, csize)
.withTrace(pos, errorCtx).debugThrow();
@ -2411,7 +2411,7 @@ std::pair<SingleDerivedPath, std::string_view> EvalState::coerceToSingleDerivedP
return std::move(o);
},
[&](NixStringContextElem::DrvDeep &&) -> SingleDerivedPath {
errors.make<EvalError>(
ctx.errors.make<EvalError>(
"string '%s' has a context which refers to a complete source and binary closure. This is not supported at this time",
s).withTrace(pos, errorCtx).debugThrow();
},
@ -2436,13 +2436,13 @@ SingleDerivedPath EvalState::coerceToSingleDerivedPath(const PosIdx pos, Value &
error message. */
std::visit(overloaded {
[&](const SingleDerivedPath::Opaque & o) {
errors.make<EvalError>(
ctx.errors.make<EvalError>(
"path string '%s' has context with the different path '%s'",
s, sExpected)
.withTrace(pos, errorCtx).debugThrow();
},
[&](const SingleDerivedPath::Built & b) {
errors.make<EvalError>(
ctx.errors.make<EvalError>(
"string '%s' has context with the output '%s' from derivation '%s', but the string is not the right placeholder for this derivation output. It should be '%s'",
s, b.output, b.drvPath->to_string(*store), sExpected)
.withTrace(pos, errorCtx).debugThrow();
@ -2527,7 +2527,7 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
case nThunk: // Must not be left by forceValue
default:
errors.make<EvalError>("cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).debugThrow();
ctx.errors.make<EvalError>("cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).debugThrow();
}
}
@ -2832,7 +2832,7 @@ std::optional<std::string> EvalPaths::resolveSearchPathPath(const SearchPath::Pa
std::string ExternalValueBase::coerceToString(EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const
{
state.errors.make<TypeError>(
state.ctx.errors.make<TypeError>(
"cannot coerce %1% to a string: %2%", showType(), *this
).atPos(pos).debugThrow();
}

View file

@ -142,14 +142,14 @@ static FlakeInput parseFlakeInput(EvalState & state,
auto intValue = attr.value->integer.value;
if (intValue < 0) {
state.errors.make<EvalError>("negative value given for flake input attribute %1%: %2%", state.ctx.symbols[attr.name], intValue).debugThrow();
state.ctx.errors.make<EvalError>("negative value given for flake input attribute %1%: %2%", state.ctx.symbols[attr.name], intValue).debugThrow();
}
uint64_t asUnsigned = intValue;
attrs.emplace(state.ctx.symbols[attr.name], asUnsigned);
break;
}
default:
state.errors.make<TypeError>("flake input attribute '%s' is %s while a string, Boolean, or integer is expected",
state.ctx.errors.make<TypeError>("flake input attribute '%s' is %s while a string, Boolean, or integer is expected",
state.ctx.symbols[attr.name], showType(*attr.value)).debugThrow();
}
#pragma GCC diagnostic pop
@ -247,7 +247,7 @@ static Flake getFlake(
// Enforce that 'flake.nix' is a direct attrset, not a computation.
if (!(dynamic_cast<ExprAttrs *>(&flakeExpr))) {
state.errors.make<EvalError>("file '%s' must be an attribute set", resolvedFlakeFile).debugThrow();
state.ctx.errors.make<EvalError>("file '%s' must be an attribute set", resolvedFlakeFile).debugThrow();
}
Value vInfo;
@ -307,14 +307,14 @@ static Flake getFlake(
std::vector<std::string> ss;
for (auto elem : setting.value->listItems()) {
if (elem->type() != nString)
state.errors.make<TypeError>("list element in flake configuration setting '%s' is %s while a string is expected",
state.ctx.errors.make<TypeError>("list element in flake configuration setting '%s' is %s while a string is expected",
state.ctx.symbols[setting.name], showType(*setting.value)).debugThrow();
ss.emplace_back(state.forceStringNoCtx(*elem, setting.pos, ""));
}
flake.config.settings.emplace(state.ctx.symbols[setting.name], ss);
}
else
state.errors.make<TypeError>("flake configuration setting '%s' is %s",
state.ctx.errors.make<TypeError>("flake configuration setting '%s' is %s",
state.ctx.symbols[setting.name], showType(*setting.value)).debugThrow();
}
}
@ -858,7 +858,7 @@ void prim_flakeRefToString(
auto intValue = attr.value->integer.value;
if (intValue < 0) {
state.errors.make<EvalError>("negative value given for flake ref attr %1%: %2%", state.ctx.symbols[attr.name], intValue).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("negative value given for flake ref attr %1%: %2%", state.ctx.symbols[attr.name], intValue).atPos(pos).debugThrow();
}
uint64_t asUnsigned = intValue;
@ -870,7 +870,7 @@ void prim_flakeRefToString(
attrs.emplace(state.ctx.symbols[attr.name],
std::string(attr.value->str()));
} else {
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"flake reference attribute sets may only contain integers, Booleans, "
"and strings, but attribute '%s' is %s",
state.ctx.symbols[attr.name],

View file

@ -50,7 +50,7 @@ std::string DrvInfo::queryName(EvalState & state)
{
if (name == "" && attrs) {
auto i = attrs->find(state.ctx.s.name);
if (i == attrs->end()) state.errors.make<TypeError>("derivation name missing").debugThrow();
if (i == attrs->end()) state.ctx.errors.make<TypeError>("derivation name missing").debugThrow();
name = state.forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation");
}
return name;
@ -431,7 +431,7 @@ static void getDerivations(EvalState & state, Value & vIn,
return;
} else if (v.type() != nAttrs) {
state.errors.make<TypeError>(
state.ctx.errors.make<TypeError>(
"expression was expected to be a derivation or collection of derivations, but instead was %s",
showType(v.type(), true)
).debugThrow();

View file

@ -285,16 +285,16 @@ void prim_importNative(EvalState & state, const PosIdx pos, Value * * args, Valu
void *handle = dlopen(path.path.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (!handle)
state.errors.make<EvalError>("could not open '%1%': %2%", path, dlerror()).debugThrow();
state.ctx.errors.make<EvalError>("could not open '%1%': %2%", path, dlerror()).debugThrow();
dlerror();
ValueInitializer func = reinterpret_cast<ValueInitializer>(dlsym(handle, sym.c_str()));
if(!func) {
char *message = dlerror();
if (message)
state.errors.make<EvalError>("could not load symbol '%1%' from '%2%': %3%", sym, path, message).debugThrow();
state.ctx.errors.make<EvalError>("could not load symbol '%1%' from '%2%': %3%", sym, path, message).debugThrow();
else
state.errors.make<EvalError>("symbol '%1%' from '%2%' resolved to NULL when a function pointer was expected", sym, path).debugThrow();
state.ctx.errors.make<EvalError>("symbol '%1%' from '%2%' resolved to NULL when a function pointer was expected", sym, path).debugThrow();
}
(func)(state, v);
@ -310,7 +310,7 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
auto elems = args[0]->listElems();
auto count = args[0]->listSize();
if (count == 0)
state.errors.make<EvalError>("at least one argument to 'exec' required").atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("at least one argument to 'exec' required").atPos(pos).debugThrow();
NixStringContext context;
auto program = state.coerceToString(pos, *elems[0], context,
"while evaluating the first element of the argument passed to builtins.exec",
@ -452,7 +452,7 @@ struct CompareValues
if (v1->type() == nInt && v2->type() == nFloat)
return v1->integer.value < v2->fpoint;
if (v1->type() != v2->type())
state.errors.make<EvalError>("cannot compare %s with %s", showType(*v1), showType(*v2)).debugThrow();
state.ctx.errors.make<EvalError>("cannot compare %s with %s", showType(*v1), showType(*v2)).debugThrow();
// Allow selecting a subset of enum values
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
@ -477,7 +477,7 @@ struct CompareValues
}
}
default:
state.errors.make<EvalError>("cannot compare %s with %s; values of that type are incomparable", showType(*v1), showType(*v2)).debugThrow();
state.ctx.errors.make<EvalError>("cannot compare %s with %s; values of that type are incomparable", showType(*v1), showType(*v2)).debugThrow();
#pragma GCC diagnostic pop
}
} catch (Error & e) {
@ -503,7 +503,7 @@ static Bindings::iterator getAttr(
{
Bindings::iterator value = attrSet->find(attrSym);
if (value == attrSet->end()) {
state.errors.make<TypeError>("attribute '%s' missing", state.ctx.symbols[attrSym]).withTrace(noPos, errorCtx).debugThrow();
state.ctx.errors.make<TypeError>("attribute '%s' missing", state.ctx.symbols[attrSym]).withTrace(noPos, errorCtx).debugThrow();
}
return value;
}
@ -572,14 +572,14 @@ static void prim_genericClosure(EvalState & state, const PosIdx pos, Value * * a
static void prim_break(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
if (auto trace = state.debug ? state.debug->traces().next() : std::nullopt) {
if (auto trace = state.ctx.debug ? state.ctx.debug->traces().next() : std::nullopt) {
auto error = EvalError(ErrorInfo {
.level = lvlInfo,
.msg = HintFmt("breakpoint reached"),
.pos = state.ctx.positions[pos],
});
state.debug->onEvalError(&error, (*trace)->env, (*trace)->expr);
state.ctx.debug->onEvalError(&error, (*trace)->env, (*trace)->expr);
}
// Return the value we were passed.
@ -591,7 +591,7 @@ static void prim_abort(EvalState & state, const PosIdx pos, Value * * args, Valu
NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context,
"while evaluating the error message passed to builtins.abort").toOwned();
state.errors.make<Abort>("evaluation aborted with the following error message: '%1%'", s).debugThrow();
state.ctx.errors.make<Abort>("evaluation aborted with the following error message: '%1%'", s).debugThrow();
}
static void prim_throw(EvalState & state, const PosIdx pos, Value * * args, Value & v)
@ -599,7 +599,7 @@ static void prim_throw(EvalState & state, const PosIdx pos, Value * * args, Valu
NixStringContext context;
auto s = state.coerceToString(pos, *args[0], context,
"while evaluating the error message passed to builtin.throw").toOwned();
state.errors.make<ThrownError>(s).debugThrow();
state.ctx.errors.make<ThrownError>(s).debugThrow();
}
static void prim_addErrorContext(EvalState & state, const PosIdx pos, Value * * args, Value & v)
@ -644,11 +644,11 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Va
std::optional<MaintainCount<int>> trylevel;
std::unique_ptr<DebugState> savedDebug;
if (state.debug) {
trylevel.emplace(state.debug->trylevel);
if (state.ctx.debug) {
trylevel.emplace(state.ctx.debug->trylevel);
if (evalSettings.ignoreExceptionsDuringTry) {
/* to prevent starting the repl from exceptions withing a tryEval, null it. */
savedDebug = std::move(state.debug);
savedDebug = std::move(state.ctx.debug);
}
}
@ -663,7 +663,7 @@ static void prim_tryEval(EvalState & state, const PosIdx pos, Value * * args, Va
// restore the debugRepl pointer if we saved it earlier.
if (savedDebug)
state.debug = std::move(savedDebug);
state.ctx.debug = std::move(savedDebug);
v.mkAttrs(attrs);
}
@ -701,11 +701,11 @@ 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 (auto last = evalSettings.builtinsTraceDebugger && state.debug
? state.debug->traces().next()
if (auto last = evalSettings.builtinsTraceDebugger && state.ctx.debug
? state.ctx.debug->traces().next()
: std::nullopt)
{
state.debug->onEvalError(nullptr, (*last)->env, (*last)->expr);
state.ctx.debug->onEvalError(nullptr, (*last)->env, (*last)->expr);
}
state.forceValue(*args[1], pos);
v = *args[1];
@ -827,7 +827,7 @@ drvName, Bindings * attrs, Value & v)
experimentalFeatureSettings.require(Xp::DynamicDerivations);
ingestionMethod = TextIngestionMethod {};
} else
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"invalid value '%s' for 'outputHashMode' attribute", s
).atPos(v).debugThrow();
};
@ -836,7 +836,7 @@ drvName, Bindings * attrs, Value & v)
outputs.clear();
for (auto & j : ss) {
if (outputs.find(j) != outputs.end())
state.errors.make<EvalError>("duplicate derivation output '%1%'", j)
state.ctx.errors.make<EvalError>("duplicate derivation output '%1%'", j)
.atPos(v)
.debugThrow();
/* !!! Check whether j is a valid attribute
@ -845,13 +845,13 @@ drvName, Bindings * attrs, Value & v)
then we'd have an attribute drvPath in
the resulting set. */
if (j == "drv")
state.errors.make<EvalError>("invalid derivation output name 'drv'")
state.ctx.errors.make<EvalError>("invalid derivation output name 'drv'")
.atPos(v)
.debugThrow();
outputs.insert(j);
}
if (outputs.empty())
state.errors.make<EvalError>("derivation cannot have an empty set of outputs")
state.ctx.errors.make<EvalError>("derivation cannot have an empty set of outputs")
.atPos(v)
.debugThrow();
};
@ -989,12 +989,12 @@ drvName, Bindings * attrs, Value & v)
/* Do we have all required attributes? */
if (drv.builder == "")
state.errors.make<EvalError>("required attribute 'builder' missing")
state.ctx.errors.make<EvalError>("required attribute 'builder' missing")
.atPos(v)
.debugThrow();
if (drv.platform == "")
state.errors.make<EvalError>("required attribute 'system' missing")
state.ctx.errors.make<EvalError>("required attribute 'system' missing")
.atPos(v)
.debugThrow();
@ -1004,7 +1004,7 @@ drvName, Bindings * attrs, Value & v)
outputs.size() == 1 &&
*(outputs.begin()) == "out"))
{
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"derivation names are allowed to end in '%s' only if they produce a single derivation file",
drvExtension
).atPos(v).debugThrow();
@ -1016,7 +1016,7 @@ drvName, Bindings * attrs, Value & v)
Ignore `__contentAddressed` because fixed output derivations are
already content addressed. */
if (outputs.size() != 1 || *(outputs.begin()) != "out")
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"multiple outputs are not supported in fixed-output derivations"
).atPos(v).debugThrow();
@ -1037,7 +1037,7 @@ drvName, Bindings * attrs, Value & v)
else if (contentAddressed || isImpure) {
if (contentAddressed && isImpure)
state.errors.make<EvalError>("derivation cannot be both content-addressed and impure")
state.ctx.errors.make<EvalError>("derivation cannot be both content-addressed and impure")
.atPos(v).debugThrow();
auto ht = parseHashTypeOpt(outputHashAlgo).value_or(HashType::SHA256);
@ -1079,7 +1079,7 @@ drvName, Bindings * attrs, Value & v)
for (auto & i : outputs) {
auto h = get(hashModulo.hashes, i);
if (!h)
state.errors.make<AssertionError>(
state.ctx.errors.make<AssertionError>(
"derivation produced no hash for output '%s'",
i
).atPos(v).debugThrow();
@ -1167,7 +1167,7 @@ static void prim_toPath(EvalState & state, const PosIdx pos, Value * * args, Val
static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args, Value & v)
{
if (evalSettings.pureEval)
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"'%s' is not allowed in pure evaluation mode",
"builtins.storePath"
).atPos(pos).debugThrow();
@ -1180,7 +1180,7 @@ static void prim_storePath(EvalState & state, const PosIdx pos, Value * * args,
if (!state.store->isStorePath(path.abs()))
path = CanonPath(canonPath(path.abs(), true));
if (!state.store->isInStore(path.abs()))
state.errors.make<EvalError>("path '%1%' is not in the Nix store", path)
state.ctx.errors.make<EvalError>("path '%1%' is not in the Nix store", path)
.atPos(pos).debugThrow();
auto path2 = state.store->toStorePath(path.abs()).first;
if (!settings.readOnlyMode)
@ -1258,7 +1258,7 @@ static void prim_readFile(EvalState & state, const PosIdx pos, Value * * args, V
auto path = realisePath(state, pos, *args[0]);
auto s = path.readFile();
if (s.find((char) 0) != std::string::npos)
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"the contents of the file '%1%' cannot be represented as a Nix string",
path
).atPos(pos).debugThrow();
@ -1309,7 +1309,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
auto rewrites = state.paths.realiseContext(context);
path = rewriteStrings(path, rewrites);
} catch (InvalidPathError & e) {
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"cannot find '%1%', since path '%2%' is not valid",
path,
e.path
@ -1333,7 +1333,7 @@ static void prim_hashFile(EvalState & state, const PosIdx pos, Value * * args, V
auto type = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashFile");
std::optional<HashType> ht = parseHashType(type);
if (!ht)
state.errors.make<EvalError>("unknown hash type '%1%'", type).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("unknown hash type '%1%'", type).atPos(pos).debugThrow();
auto path = realisePath(state, pos, *args[1]);
@ -1462,7 +1462,7 @@ static void prim_toFile(EvalState & state, const PosIdx pos, Value * * args, Val
if (auto p = std::get_if<NixStringContextElem::Opaque>(&c.raw))
refs.insert(p->path);
else
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"files created by %1% may not reference derivations, but %2% references %3%",
"builtins.toFile",
name,
@ -1549,7 +1549,7 @@ static void addPath(
auto dstPath = fetchToStore(
*state.store, CanonPath(path), name, method, &filter, state.repair);
if (expectedHash && expectedStorePath != dstPath)
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"store path mismatch in (possibly filtered) path added from '%s'",
path
).atPos(pos).debugThrow();
@ -1596,13 +1596,13 @@ static void prim_path(EvalState & state, const PosIdx pos, Value * * args, Value
else if (n == "sha256")
expectedHash = newHashAllowEmpty(state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `sha256` attribute passed to builtins.path"), HashType::SHA256);
else
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"unsupported argument '%1%' to 'addPath'",
state.ctx.symbols[attr.name]
).atPos(attr.pos).debugThrow();
}
if (!path)
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"missing required 'path' attribute in the first argument to builtins.path"
).atPos(pos).debugThrow();
if (name.empty())
@ -1909,7 +1909,7 @@ static void prim_functionArgs(EvalState & state, const PosIdx pos, Value * * arg
return;
}
if (!args[0]->isLambda())
state.errors.make<TypeError>("'functionArgs' requires a function").atPos(pos).debugThrow();
state.ctx.errors.make<TypeError>("'functionArgs' requires a function").atPos(pos).debugThrow();
if (!args[0]->lambda.fun->hasFormals()) {
v.mkAttrs(&Bindings::EMPTY);
@ -2006,7 +2006,7 @@ static void elemAt(EvalState & state, const PosIdx pos, Value & list, int n, Val
{
state.forceList(list, pos, "while evaluating the first argument passed to builtins.elemAt");
if (n < 0 || (unsigned int) n >= list.listSize())
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"list index %1% is out of bounds",
n
).atPos(pos).debugThrow();
@ -2034,7 +2034,7 @@ static void prim_tail(EvalState & state, const PosIdx pos, Value * * args, Value
{
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.tail");
if (args[0]->listSize() == 0)
state.errors.make<EvalError>("'tail' called on an empty list").atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("'tail' called on an empty list").atPos(pos).debugThrow();
v = state.mem.newList(args[0]->listSize() - 1);
for (unsigned int n = 0; n < v.listSize(); ++n)
@ -2181,7 +2181,7 @@ static void prim_genList(EvalState & state, const PosIdx pos, Value * * args, Va
auto len_ = state.forceInt(*args[1], pos, "while evaluating the second argument passed to builtins.genList").value;
if (len_ < 0)
state.errors.make<EvalError>("cannot create list of size %1%", len_).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("cannot create list of size %1%", len_).atPos(pos).debugThrow();
size_t len = len_;
@ -2354,7 +2354,7 @@ static void prim_add(EvalState & state, const PosIdx pos, Value * * args, Value
if (auto result = result_.valueChecked(); result.has_value()) {
v.mkInt(*result);
} else {
state.errors.make<EvalError>("integer overflow in adding %1% + %2%", i1, i2).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("integer overflow in adding %1% + %2%", i1, i2).atPos(pos).debugThrow();
}
}
}
@ -2375,7 +2375,7 @@ static void prim_sub(EvalState & state, const PosIdx pos, Value * * args, Value
if (auto result = result_.valueChecked(); result.has_value()) {
v.mkInt(*result);
} else {
state.errors.make<EvalError>("integer overflow in subtracting %1% - %2%", i1, i2).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("integer overflow in subtracting %1% - %2%", i1, i2).atPos(pos).debugThrow();
}
}
}
@ -2396,7 +2396,7 @@ static void prim_mul(EvalState & state, const PosIdx pos, Value * * args, Value
if (auto result = result_.valueChecked(); result.has_value()) {
v.mkInt(*result);
} else {
state.errors.make<EvalError>("integer overflow in multiplying %1% * %2%", i1, i2).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("integer overflow in multiplying %1% * %2%", i1, i2).atPos(pos).debugThrow();
}
}
}
@ -2408,7 +2408,7 @@ static void prim_div(EvalState & state, const PosIdx pos, Value * * args, Value
NixFloat f2 = state.forceFloat(*args[1], pos, "while evaluating the second operand of the division");
if (f2 == 0)
state.errors.make<EvalError>("division by zero").atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("division by zero").atPos(pos).debugThrow();
if (args[0]->type() == nFloat || args[1]->type() == nFloat) {
v.mkFloat(state.forceFloat(*args[0], pos, "while evaluating the first operand of the division") / f2);
@ -2420,7 +2420,7 @@ static void prim_div(EvalState & state, const PosIdx pos, Value * * args, Value
if (auto result = result_.valueChecked(); result.has_value()) {
v.mkInt(*result);
} else {
state.errors.make<EvalError>("integer overflow in dividing %1% / %2%", i1, i2).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("integer overflow in dividing %1% / %2%", i1, i2).atPos(pos).debugThrow();
}
}
}
@ -2484,7 +2484,7 @@ static void prim_substring(EvalState & state, const PosIdx pos, Value * * args,
NixInt::Inner start = state.forceInt(*args[0], pos, "while evaluating the first argument (the start offset) passed to builtins.substring").value;
if (start < 0)
state.errors.make<EvalError>("negative start position in 'substring'").atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("negative start position in 'substring'").atPos(pos).debugThrow();
NixInt::Inner len = state.forceInt(*args[1], pos, "while evaluating the second argument (the substring length) passed to builtins.substring").value;
@ -2524,7 +2524,7 @@ static void prim_hashString(EvalState & state, const PosIdx pos, Value * * args,
auto type = state.forceStringNoCtx(*args[0], pos, "while evaluating the first argument passed to builtins.hashString");
std::optional<HashType> ht = parseHashType(type);
if (!ht)
state.errors.make<EvalError>("unknown hash algorithm '%1%'", type).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("unknown hash algorithm '%1%'", type).atPos(pos).debugThrow();
NixStringContext context; // discarded
auto s = state.forceString(*args[1], context, pos, "while evaluating the second argument passed to builtins.hashString");
@ -2586,11 +2586,11 @@ void prim_match(EvalState & state, const PosIdx pos, Value * * args, Value & v)
} catch (std::regex_error & e) {
if (e.code() == std::regex_constants::error_space) {
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
state.errors.make<EvalError>("memory limit exceeded by regular expression '%s'", re)
state.ctx.errors.make<EvalError>("memory limit exceeded by regular expression '%s'", re)
.atPos(pos)
.debugThrow();
} else
state.errors.make<EvalError>("invalid regular expression '%s'", re)
state.ctx.errors.make<EvalError>("invalid regular expression '%s'", re)
.atPos(pos)
.debugThrow();
}
@ -2652,11 +2652,11 @@ void prim_split(EvalState & state, const PosIdx pos, Value * * args, Value & v)
} catch (std::regex_error & e) {
if (e.code() == std::regex_constants::error_space) {
// limit is _GLIBCXX_REGEX_STATE_LIMIT for libstdc++
state.errors.make<EvalError>("memory limit exceeded by regular expression '%s'", re)
state.ctx.errors.make<EvalError>("memory limit exceeded by regular expression '%s'", re)
.atPos(pos)
.debugThrow();
} else
state.errors.make<EvalError>("invalid regular expression '%s'", re)
state.ctx.errors.make<EvalError>("invalid regular expression '%s'", re)
.atPos(pos)
.debugThrow();
}
@ -2686,7 +2686,7 @@ static void prim_replaceStrings(EvalState & state, const PosIdx pos, Value * * a
state.forceList(*args[0], pos, "while evaluating the first argument passed to builtins.replaceStrings");
state.forceList(*args[1], pos, "while evaluating the second argument passed to builtins.replaceStrings");
if (args[0]->listSize() != args[1]->listSize())
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"'from' and 'to' arguments passed to builtins.replaceStrings have different lengths"
).atPos(pos).debugThrow();

View file

@ -56,7 +56,7 @@ void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, Value *
auto contextSize = context.size();
if (contextSize != 1) {
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"context of string '%s' must have exactly one element, but has %d",
*s,
contextSize
@ -66,7 +66,7 @@ void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, Value *
(NixStringContextElem { std::visit(overloaded {
[&](const NixStringContextElem::Opaque & c) -> NixStringContextElem::DrvDeep {
if (!c.path.isDerivation()) {
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"path '%s' is not a derivation",
state.store->printStorePath(c.path)
).atPos(pos).debugThrow();
@ -76,7 +76,7 @@ void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, Value *
};
},
[&](const NixStringContextElem::Built & c) -> NixStringContextElem::DrvDeep {
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"`addDrvOutputDependencies` can only act on derivations, not on a derivation output such as '%1%'",
c.output
).atPos(pos).debugThrow();
@ -176,7 +176,7 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
for (auto & i : *args[1]->attrs) {
const auto & name = state.ctx.symbols[i.name];
if (!state.store->isStorePath(name))
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"context key '%s' is not a store path",
name
).atPos(i.pos).debugThrow();
@ -196,7 +196,7 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
if (iter != i.value->attrs->end()) {
if (state.forceBool(*iter->value, iter->pos, "while evaluating the `allOutputs` attribute of a string context")) {
if (!isDerivation(name)) {
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"tried to add all-outputs context of %s, which is not a derivation, to a string",
name
).atPos(i.pos).debugThrow();
@ -211,7 +211,7 @@ static void prim_appendContext(EvalState & state, const PosIdx pos, Value * * ar
if (iter != i.value->attrs->end()) {
state.forceList(*iter->value, iter->pos, "while evaluating the `outputs` attribute of a string context");
if (iter->value->listSize() && !isDerivation(name)) {
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"tried to add derivation output context of %s, which is not a derivation, to a string",
name
).atPos(i.pos).debugThrow();

View file

@ -38,11 +38,11 @@ static void prim_fetchMercurial(EvalState & state, const PosIdx pos, Value * * a
else if (n == "name")
name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the `name` attribute passed to builtins.fetchMercurial");
else
state.errors.make<EvalError>("unsupported argument '%s' to 'fetchMercurial'", state.ctx.symbols[attr.name]).atPos(attr.pos).debugThrow();
state.ctx.errors.make<EvalError>("unsupported argument '%s' to 'fetchMercurial'", state.ctx.symbols[attr.name]).atPos(attr.pos).debugThrow();
}
if (url.empty())
state.errors.make<EvalError>("'url' argument required").atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("'url' argument required").atPos(pos).debugThrow();
} else
url = state.coerceToString(pos, *args[0], context,

View file

@ -124,12 +124,12 @@ static void fetchTree(
if (auto aType = args[0]->attrs->get(state.ctx.s.type)) {
if (type)
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"unexpected attribute 'type'"
).atPos(pos).debugThrow();
type = state.forceStringNoCtx(*aType->value, aType->pos, "while evaluating the `type` attribute passed to builtins.fetchTree");
} else if (!type)
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"attribute 'type' is missing in call to 'fetchTree'"
).atPos(pos).debugThrow();
@ -153,19 +153,19 @@ static void fetchTree(
auto intValue = attr.value->integer.value;
if (intValue < 0) {
state.errors.make<EvalError>("negative value given for fetchTree attr %1%: %2%", state.ctx.symbols[attr.name], intValue).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("negative value given for fetchTree attr %1%: %2%", state.ctx.symbols[attr.name], intValue).atPos(pos).debugThrow();
}
unsigned long asUnsigned = intValue;
attrs.emplace(state.ctx.symbols[attr.name], asUnsigned);
} else
state.errors.make<TypeError>("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
state.ctx.errors.make<TypeError>("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
state.ctx.symbols[attr.name], showType(*attr.value)).debugThrow();
}
if (!params.allowNameArgument)
if (auto nameIter = attrs.find("name"); nameIter != attrs.end())
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"attribute 'name' isnt supported in call to 'fetchTree'"
).atPos(pos).debugThrow();
@ -189,7 +189,7 @@ static void fetchTree(
input = lookupInRegistries(state.store, input).first;
if (evalSettings.pureEval && !input.isLocked()) {
state.errors.make<EvalError>("in pure evaluation mode, 'fetchTree' requires a locked input").atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("in pure evaluation mode, 'fetchTree' requires a locked input").atPos(pos).debugThrow();
}
auto [tree, input2] = input.fetch(state.store);
@ -231,12 +231,12 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
else if (n == "name")
name = state.forceStringNoCtx(*attr.value, attr.pos, "while evaluating the name of the content we should fetch");
else
state.errors.make<EvalError>("unsupported argument '%s' to '%s'", n, who)
state.ctx.errors.make<EvalError>("unsupported argument '%s' to '%s'", n, who)
.atPos(pos).debugThrow();
}
if (!url)
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"'url' argument required").atPos(pos).debugThrow();
} else
url = state.forceStringNoCtx(*args[0], pos, "while evaluating the url we should fetch");
@ -250,7 +250,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
name = baseNameOf(*url);
if (evalSettings.pureEval && !expectedHash)
state.errors.make<EvalError>("in pure evaluation mode, '%s' requires a 'sha256' argument", who).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("in pure evaluation mode, '%s' requires a 'sha256' argument", who).atPos(pos).debugThrow();
// early exit if pinned and already in the store
if (expectedHash && expectedHash->type == HashType::SHA256) {
@ -280,7 +280,7 @@ static void fetch(EvalState & state, const PosIdx pos, Value * * args, Value & v
? state.store->queryPathInfo(storePath)->narHash
: hashFile(HashType::SHA256, state.store->toRealPath(storePath));
if (hash != *expectedHash) {
state.errors.make<EvalError>(
state.ctx.errors.make<EvalError>(
"hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s",
*url,
expectedHash->to_string(Base::Base32, true),

View file

@ -83,7 +83,7 @@ void prim_fromTOML(EvalState & state, const PosIdx pos, Value * * args, Value &
try {
visit(val, toml::parse(tomlStream, "fromTOML" /* the "filename" */));
} catch (std::exception & e) { // TODO: toml::syntax_error
state.errors.make<EvalError>("while parsing TOML: %s", e.what()).atPos(pos).debugThrow();
state.ctx.errors.make<EvalError>("while parsing TOML: %s", e.what()).atPos(pos).debugThrow();
}
}

View file

@ -99,7 +99,7 @@ json printValueAsJSON(EvalState & state, bool strict,
case nThunk:
case nFunction:
state.errors.make<TypeError>(
state.ctx.errors.make<TypeError>(
"cannot convert %1% to JSON",
showType(v)
)
@ -118,7 +118,7 @@ void printValueAsJSON(EvalState & state, bool strict,
json ExternalValueBase::printValueAsJSON(EvalState & state, bool strict,
NixStringContext & context, bool copyToStore) const
{
state.errors.make<TypeError>("cannot convert %1% to JSON", showType())
state.ctx.errors.make<TypeError>("cannot convert %1% to JSON", showType())
.debugThrow();
}