libexpr: extract eval error creation into new type
this will let us pass the capability to create debuggable eval errors
without having to pass an entire EvalState. we could pass symbols and
debug states around just as easily, but if we add new capabilities to
our debugger we might have to change many more places than with this.
Change-Id: I2f8893012e5d98a986ef1fc888234c2dd8d5e096
This commit is contained in:
parent
a4fa93d469
commit
a65e9e5828
|
@ -988,7 +988,7 @@ Value * NixRepl::replOverlays()
|
|||
auto replInit = evalFile(sourcePath);
|
||||
|
||||
if (!replInit->isLambda()) {
|
||||
state.error<TypeError>(
|
||||
state.errors.make<TypeError>(
|
||||
"Expected `repl-overlays` to be a lambda but found %1%: %2%",
|
||||
showType(*replInit),
|
||||
ValuePrinter(state, *replInit, errorPrintOptions)
|
||||
|
@ -999,7 +999,7 @@ Value * NixRepl::replOverlays()
|
|||
|
||||
if (replInit->lambda.fun->hasFormals()
|
||||
&& !replInit->lambda.fun->formals->ellipsis) {
|
||||
state.error<TypeError>(
|
||||
state.errors.make<TypeError>(
|
||||
"Expected first argument of %1% to have %2% to allow future versions of Lix to add additional attributes to the argument",
|
||||
"repl-overlays",
|
||||
"..."
|
||||
|
|
|
@ -65,7 +65,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
|||
if (!attrIndex) {
|
||||
|
||||
if (v->type() != nAttrs)
|
||||
state.error<TypeError>(
|
||||
state.errors.make<TypeError>(
|
||||
"the expression selected by the selection path '%1%' should be a set but is %2%",
|
||||
attrPath,
|
||||
showType(*v)).debugThrow();
|
||||
|
@ -88,7 +88,7 @@ std::pair<Value *, PosIdx> findAlongAttrPath(EvalState & state, const std::strin
|
|||
else {
|
||||
|
||||
if (!v->isList())
|
||||
state.error<TypeError>(
|
||||
state.errors.make<TypeError>(
|
||||
"the expression selected by the selection path '%1%' should be a list but is %2%",
|
||||
attrPath,
|
||||
showType(*v)).debugThrow();
|
||||
|
|
|
@ -506,7 +506,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
|
|||
// evaluate to see whether 'name' exists
|
||||
} else
|
||||
return nullptr;
|
||||
//error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
//errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -514,7 +514,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
|
|||
|
||||
if (v.type() != nAttrs)
|
||||
return nullptr;
|
||||
//error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
//errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
|
||||
auto attr = v.attrs->get(name);
|
||||
|
||||
|
@ -580,14 +580,14 @@ std::string AttrCursor::getString()
|
|||
debug("using cached string attribute '%s'", getAttrPathStr());
|
||||
return s->first;
|
||||
} else
|
||||
root->state.error<TypeError>("'%s' is not a string", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not a string", getAttrPathStr()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() != nString && v.type() != nPath) {
|
||||
root->state.error<TypeError>("'%s' is not a string but %s", getAttrPathStr(), v.type()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not a string but %s", getAttrPathStr(), v.type()).debugThrow();
|
||||
}
|
||||
|
||||
return v.type() == nString ? v.string.s : v.path().to_string();
|
||||
|
@ -623,7 +623,7 @@ string_t AttrCursor::getStringWithContext()
|
|||
return *s;
|
||||
}
|
||||
} else
|
||||
root->state.error<TypeError>("'%s' is not a string", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not a string", getAttrPathStr()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -636,7 +636,7 @@ string_t AttrCursor::getStringWithContext()
|
|||
} else if (v.type() == nPath) {
|
||||
return {v.path().to_string(), {}};
|
||||
} else {
|
||||
root->state.error<TypeError>("'%s' is not a string but %s", getAttrPathStr(), v.type()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not a string but %s", getAttrPathStr(), v.type()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -650,14 +650,14 @@ bool AttrCursor::getBool()
|
|||
debug("using cached Boolean attribute '%s'", getAttrPathStr());
|
||||
return *b;
|
||||
} else
|
||||
root->state.error<TypeError>("'%s' is not a Boolean", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() != nBool)
|
||||
root->state.error<TypeError>("'%s' is not a Boolean", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not a Boolean", getAttrPathStr()).debugThrow();
|
||||
|
||||
return v.boolean;
|
||||
}
|
||||
|
@ -672,14 +672,14 @@ NixInt AttrCursor::getInt()
|
|||
debug("using cached integer attribute '%s'", getAttrPathStr());
|
||||
return i->x;
|
||||
} else
|
||||
root->state.error<TypeError>("'%s' is not an integer", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() != nInt)
|
||||
root->state.error<TypeError>("'%s' is not an integer", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not an integer", getAttrPathStr()).debugThrow();
|
||||
|
||||
return v.integer;
|
||||
}
|
||||
|
@ -694,7 +694,7 @@ std::vector<std::string> AttrCursor::getListOfStrings()
|
|||
debug("using cached list of strings attribute '%s'", getAttrPathStr());
|
||||
return *l;
|
||||
} else
|
||||
root->state.error<TypeError>("'%s' is not a list of strings", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not a list of strings", getAttrPathStr()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -704,7 +704,7 @@ std::vector<std::string> AttrCursor::getListOfStrings()
|
|||
root->state.forceValue(v, noPos);
|
||||
|
||||
if (v.type() != nList)
|
||||
root->state.error<TypeError>("'%s' is not a list", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not a list", getAttrPathStr()).debugThrow();
|
||||
|
||||
std::vector<std::string> res;
|
||||
|
||||
|
@ -727,14 +727,14 @@ std::vector<Symbol> AttrCursor::getAttrs()
|
|||
debug("using cached attrset attribute '%s'", getAttrPathStr());
|
||||
return *attrs;
|
||||
} else
|
||||
root->state.error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
auto & v = forceValue();
|
||||
|
||||
if (v.type() != nAttrs)
|
||||
root->state.error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
root->state.errors.make<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
|
||||
|
||||
std::vector<Symbol> attrs;
|
||||
for (auto & attr : *getValue().attrs)
|
||||
|
|
|
@ -14,7 +14,7 @@ EvalErrorBuilder<T> EvalErrorBuilder<T>::withExitStatus(unsigned int exitStatus)
|
|||
template<class T>
|
||||
EvalErrorBuilder<T> EvalErrorBuilder<T>::atPos(PosIdx pos) &&
|
||||
{
|
||||
error->err.pos = state.positions[pos];
|
||||
error->err.pos = positions[pos];
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ template<class T>
|
|||
EvalErrorBuilder<T> EvalErrorBuilder<T>::withTrace(PosIdx pos, const std::string_view text) &&
|
||||
{
|
||||
error->err.traces.push_front(
|
||||
Trace{.pos = state.positions[pos], .hint = HintFmt(std::string(text))});
|
||||
Trace{.pos = positions[pos], .hint = HintFmt(std::string(text))});
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
|
@ -42,9 +42,9 @@ EvalErrorBuilder<T> EvalErrorBuilder<T>::withSuggestions(Suggestions & s) &&
|
|||
template<class T>
|
||||
EvalErrorBuilder<T> EvalErrorBuilder<T>::withFrame(const Env & env, const Expr & expr) &&
|
||||
{
|
||||
if (state.debug) {
|
||||
error->frame = state.debug->addTrace(DebugTrace{
|
||||
.pos = state.positions[expr.getPos()],
|
||||
if (debug) {
|
||||
error->frame = debug->addTrace(DebugTrace{
|
||||
.pos = positions[expr.getPos()],
|
||||
.expr = expr,
|
||||
.env = env,
|
||||
.hint = HintFmt("Fake frame for debugging purposes"),
|
||||
|
@ -57,7 +57,7 @@ EvalErrorBuilder<T> EvalErrorBuilder<T>::withFrame(const Env & env, const Expr &
|
|||
template<class T>
|
||||
EvalErrorBuilder<T> EvalErrorBuilder<T>::addTrace(PosIdx pos, HintFmt hint) &&
|
||||
{
|
||||
error->addTrace(state.positions[pos], hint);
|
||||
error->addTrace(positions[pos], hint);
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
|
@ -67,18 +67,18 @@ EvalErrorBuilder<T>
|
|||
EvalErrorBuilder<T>::addTrace(PosIdx pos, std::string_view formatString, const Args &... formatArgs) &&
|
||||
{
|
||||
|
||||
addTrace(state.positions[pos], HintFmt(std::string(formatString), formatArgs...));
|
||||
addTrace(positions[pos], HintFmt(std::string(formatString), formatArgs...));
|
||||
return std::move(*this);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void EvalErrorBuilder<T>::debugThrow() &&
|
||||
{
|
||||
if (state.debug) {
|
||||
if (auto last = state.debug->traces().next()) {
|
||||
if (debug) {
|
||||
if (auto last = debug->traces().next()) {
|
||||
const Env * env = &(*last)->env;
|
||||
const Expr * expr = &(*last)->expr;
|
||||
state.debug->onEvalError(error.get(), *env, *expr);
|
||||
debug->onEvalError(error.get(), *env, *expr);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,9 +5,11 @@
|
|||
#include "lix/libutil/error.hh"
|
||||
#include "lix/libutil/types.hh"
|
||||
#include "lix/libexpr/pos-idx.hh"
|
||||
#include "lix/libexpr/pos-table.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct DebugState;
|
||||
struct DebugTrace;
|
||||
struct Env;
|
||||
struct Expr;
|
||||
|
@ -55,18 +57,18 @@ public:
|
|||
template<class T>
|
||||
class [[nodiscard]] EvalErrorBuilder final
|
||||
{
|
||||
friend class EvalState;
|
||||
|
||||
EvalState & state;
|
||||
|
||||
template<typename... Args>
|
||||
explicit EvalErrorBuilder(EvalState & state, const Args &... args)
|
||||
: state(state), error(make_box_ptr<T>(args...))
|
||||
{
|
||||
}
|
||||
const PosTable & positions;
|
||||
DebugState * debug;
|
||||
box_ptr<T> error;
|
||||
|
||||
public:
|
||||
box_ptr<T> error;
|
||||
template<typename... Args>
|
||||
explicit EvalErrorBuilder(const PosTable & positions, DebugState * debug, const Args &... args)
|
||||
: positions(positions)
|
||||
, debug{debug}
|
||||
, error(make_box_ptr<T>(args...))
|
||||
{
|
||||
}
|
||||
|
||||
[[gnu::noinline]] EvalErrorBuilder<T> withExitStatus(unsigned int exitStatus) &&;
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ inline void EvalState::forceAttrs(Value & v, const PosIdx pos, std::string_view
|
|||
{
|
||||
forceValue(v, pos);
|
||||
if (v.type() != nAttrs) {
|
||||
error<TypeError>(
|
||||
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()) {
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"expected a list but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
|
|
@ -299,6 +299,7 @@ EvalState::EvalState(
|
|||
)
|
||||
: nullptr
|
||||
}
|
||||
, errors{positions, debug.get()}
|
||||
{
|
||||
countCalls = getEnv("NIX_COUNT_CALLS").value_or("0") != "0";
|
||||
|
||||
|
@ -750,7 +751,7 @@ inline Value * EvalState::lookupVar(Env * env, const ExprVar & var, bool noEval)
|
|||
return j->value;
|
||||
}
|
||||
if (!fromWith->parentWith)
|
||||
error<UndefinedVarError>("undefined variable '%1%'", symbols[var.name]).atPos(var.pos).withFrame(*env, var).debugThrow();
|
||||
errors.make<UndefinedVarError>("undefined variable '%1%'", symbols[var.name]).atPos(var.pos).withFrame(*env, var).debugThrow();
|
||||
for (size_t l = fromWith->prevWith; l; --l, env = env->up) ;
|
||||
fromWith = fromWith->parentWith;
|
||||
}
|
||||
|
@ -981,7 +982,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)
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"expected a Boolean but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
@ -999,7 +1000,7 @@ inline void EvalState::evalAttrs(Env & env, Expr & e, Value & v, const PosIdx po
|
|||
try {
|
||||
e.eval(*this, env, v);
|
||||
if (v.type() != nAttrs)
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"expected a set but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
@ -1131,7 +1132,7 @@ void ExprAttrs::eval(EvalState & state, Env & env, Value & v)
|
|||
auto nameSym = state.symbols.create(nameVal.string.s);
|
||||
Bindings::iterator j = v.attrs->find(nameSym);
|
||||
if (j != v.attrs->end())
|
||||
state.error<EvalError>("dynamic attribute '%1%' already defined at %2%", state.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.symbols[nameSym], state.positions[j->pos]).atPos(i.pos).withFrame(env, *this).debugThrow();
|
||||
|
||||
i.valueExpr->setName(nameSym);
|
||||
/* Keep sorted order so find can catch duplicates */
|
||||
|
@ -1306,7 +1307,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
|||
}
|
||||
|
||||
// Otherwise, we must type error.
|
||||
state.error<TypeError>(
|
||||
state.errors.make<TypeError>(
|
||||
"expected a set but found %s: %s",
|
||||
showType(*vCurrent),
|
||||
ValuePrinter(state, *vCurrent, errorPrintOptions)
|
||||
|
@ -1333,7 +1334,7 @@ void ExprSelect::eval(EvalState & state, Env & env, Value & v)
|
|||
allAttrNames.insert(state.symbols[attr.name]);
|
||||
}
|
||||
auto suggestions = Suggestions::bestMatches(allAttrNames, state.symbols[name]);
|
||||
state.error<EvalError>("attribute '%s' missing", state.symbols[name])
|
||||
state.errors.make<EvalError>("attribute '%s' missing", state.symbols[name])
|
||||
.atPos(pos)
|
||||
.withSuggestions(suggestions)
|
||||
.withFrame(env, *this)
|
||||
|
@ -1469,7 +1470,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)
|
||||
error<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
|
||||
errors.make<EvalError>("stack overflow; max-call-depth exceeded").atPos(pos).debugThrow();
|
||||
CallDepth _level(callDepth);
|
||||
|
||||
auto trace = evalSettings.traceFunctionCalls
|
||||
|
@ -1531,7 +1532,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
|||
);
|
||||
for (auto const & missingArg : formalsMatch.missing) {
|
||||
auto const missing = symbols[missingArg];
|
||||
error<TypeError>("function '%s' called without required argument '%s'", lambda.getName(symbols), missing)
|
||||
errors.make<TypeError>("function '%s' called without required argument '%s'", lambda.getName(symbols), missing)
|
||||
.atPos(lambda.pos)
|
||||
.withTrace(pos, "from call site")
|
||||
.withFrame(*fun.lambda.env, lambda)
|
||||
|
@ -1544,7 +1545,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
|||
formalNames.insert(symbols[formal.name]);
|
||||
}
|
||||
auto sug = Suggestions::bestMatches(formalNames, unex);
|
||||
error<TypeError>("function '%s' called with unexpected argument '%s'", lambda.getName(symbols), unex)
|
||||
errors.make<TypeError>("function '%s' called with unexpected argument '%s'", lambda.getName(symbols), unex)
|
||||
.atPos(lambda.pos)
|
||||
.withTrace(pos, "from call site")
|
||||
.withSuggestions(sug)
|
||||
|
@ -1685,7 +1686,7 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
|
|||
}
|
||||
|
||||
else
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"attempt to call something which is not a function but %1%: %2%",
|
||||
showType(vCur),
|
||||
ValuePrinter(*this, vCur, errorPrintOptions))
|
||||
|
@ -1772,7 +1773,7 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
|
|||
if (j != args.end()) {
|
||||
attrs.insert(*j);
|
||||
} else if (!i.def) {
|
||||
error<MissingArgumentError>(R"(cannot evaluate a function that has an argument without a value ('%1%')
|
||||
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
|
||||
|
@ -1808,7 +1809,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.symbols, out);
|
||||
state.error<AssertionError>("assertion '%1%' failed", out.str()).atPos(pos).withFrame(env, *this).debugThrow();
|
||||
state.errors.make<AssertionError>("assertion '%1%' failed", out.str()).atPos(pos).withFrame(env, *this).debugThrow();
|
||||
}
|
||||
body->eval(state, env, v);
|
||||
}
|
||||
|
@ -1983,7 +1984,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
|||
if (auto checked = newN.valueChecked(); checked.has_value()) {
|
||||
n = NixInt(*checked);
|
||||
} else {
|
||||
state.error<EvalError>("integer overflow in adding %1% + %2%", n, vTmp.integer).atPos(i_pos).debugThrow();
|
||||
state.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;
|
||||
|
@ -1991,14 +1992,14 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
|||
nf = n.value;
|
||||
nf += vTmp.fpoint;
|
||||
} else
|
||||
state.error<EvalError>("cannot add %1% to an integer", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow();
|
||||
state.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.error<EvalError>("cannot add %1% to a float", showType(vTmp)).atPos(i_pos).withFrame(env, *this).debugThrow();
|
||||
state.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
|
||||
|
@ -2020,7 +2021,7 @@ void ExprConcatStrings::eval(EvalState & state, Env & env, Value & v)
|
|||
v.mkFloat(nf);
|
||||
else if (firstType == nPath) {
|
||||
if (!context.empty())
|
||||
state.error<EvalError>("a string that refers to a store path cannot be appended to a path").atPos(pos).withFrame(env, *this).debugThrow();
|
||||
state.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);
|
||||
|
@ -2035,7 +2036,7 @@ void ExprPos::eval(EvalState & state, Env & env, Value & v)
|
|||
|
||||
void ExprBlackHole::eval(EvalState & state, Env & env, Value & v)
|
||||
{
|
||||
state.error<InfiniteRecursionError>("infinite recursion encountered")
|
||||
state.errors.make<InfiniteRecursionError>("infinite recursion encountered")
|
||||
.atPos(v.determinePos(noPos))
|
||||
.debugThrow();
|
||||
}
|
||||
|
@ -2099,7 +2100,7 @@ NixInt EvalState::forceInt(Value & v, const PosIdx pos, std::string_view errorCt
|
|||
try {
|
||||
forceValue(v, pos);
|
||||
if (v.type() != nInt)
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"expected an integer but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
@ -2121,7 +2122,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)
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"expected a float but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
@ -2139,7 +2140,7 @@ bool EvalState::forceBool(Value & v, const PosIdx pos, std::string_view errorCtx
|
|||
try {
|
||||
forceValue(v, pos);
|
||||
if (v.type() != nBool)
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"expected a Boolean but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
@ -2165,7 +2166,7 @@ void EvalState::forceFunction(Value & v, const PosIdx pos, std::string_view erro
|
|||
try {
|
||||
forceValue(v, pos);
|
||||
if (v.type() != nFunction && !isFunctor(v))
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"expected a function but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
@ -2182,7 +2183,7 @@ std::string_view EvalState::forceString(Value & v, const PosIdx pos, std::string
|
|||
try {
|
||||
forceValue(v, pos);
|
||||
if (v.type() != nString)
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"expected a string but found %1%: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
@ -2215,7 +2216,7 @@ std::string_view EvalState::forceStringNoCtx(Value & v, const PosIdx pos, std::s
|
|||
{
|
||||
auto s = forceString(v, pos, errorCtx);
|
||||
if (v.string.context) {
|
||||
error<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();
|
||||
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;
|
||||
}
|
||||
|
@ -2280,7 +2281,7 @@ BackedStringView EvalState::coerceToString(
|
|||
return std::move(*maybeString);
|
||||
auto i = v.attrs->find(s.outPath);
|
||||
if (i == v.attrs->end()) {
|
||||
error<TypeError>(
|
||||
errors.make<TypeError>(
|
||||
"cannot coerce %1% to a string: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
|
@ -2330,7 +2331,7 @@ BackedStringView EvalState::coerceToString(
|
|||
}
|
||||
}
|
||||
|
||||
error<TypeError>("cannot coerce %1% to a string: %2%",
|
||||
errors.make<TypeError>("cannot coerce %1% to a string: %2%",
|
||||
showType(v),
|
||||
ValuePrinter(*this, v, errorPrintOptions)
|
||||
)
|
||||
|
@ -2342,7 +2343,7 @@ BackedStringView EvalState::coerceToString(
|
|||
StorePath EvalState::copyPathToStore(NixStringContext & context, const SourcePath & path)
|
||||
{
|
||||
if (nix::isDerivation(path.path.abs()))
|
||||
error<EvalError>("file names are not allowed to end in '%1%'", drvExtension).debugThrow();
|
||||
errors.make<EvalError>("file names are not allowed to end in '%1%'", drvExtension).debugThrow();
|
||||
|
||||
auto i = srcToStore.find(path);
|
||||
|
||||
|
@ -2367,7 +2368,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] != '/')
|
||||
error<EvalError>("string '%1%' doesn't represent an absolute path", path).withTrace(pos, errorCtx).debugThrow();
|
||||
errors.make<EvalError>("string '%1%' doesn't represent an absolute path", path).withTrace(pos, errorCtx).debugThrow();
|
||||
return CanonPath(path);
|
||||
}
|
||||
|
||||
|
@ -2377,7 +2378,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;
|
||||
error<EvalError>("path '%1%' is not in the Nix store", path).withTrace(pos, errorCtx).debugThrow();
|
||||
errors.make<EvalError>("path '%1%' is not in the Nix store", path).withTrace(pos, errorCtx).debugThrow();
|
||||
}
|
||||
|
||||
|
||||
|
@ -2387,7 +2388,7 @@ std::pair<SingleDerivedPath, std::string_view> EvalState::coerceToSingleDerivedP
|
|||
auto s = forceString(v, context, pos, errorCtx);
|
||||
auto csize = context.size();
|
||||
if (csize != 1)
|
||||
error<EvalError>(
|
||||
errors.make<EvalError>(
|
||||
"string '%s' has %d entries in its context. It should only have exactly one entry",
|
||||
s, csize)
|
||||
.withTrace(pos, errorCtx).debugThrow();
|
||||
|
@ -2396,7 +2397,7 @@ std::pair<SingleDerivedPath, std::string_view> EvalState::coerceToSingleDerivedP
|
|||
return std::move(o);
|
||||
},
|
||||
[&](NixStringContextElem::DrvDeep &&) -> SingleDerivedPath {
|
||||
error<EvalError>(
|
||||
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();
|
||||
},
|
||||
|
@ -2421,13 +2422,13 @@ SingleDerivedPath EvalState::coerceToSingleDerivedPath(const PosIdx pos, Value &
|
|||
error message. */
|
||||
std::visit(overloaded {
|
||||
[&](const SingleDerivedPath::Opaque & o) {
|
||||
error<EvalError>(
|
||||
errors.make<EvalError>(
|
||||
"path string '%s' has context with the different path '%s'",
|
||||
s, sExpected)
|
||||
.withTrace(pos, errorCtx).debugThrow();
|
||||
},
|
||||
[&](const SingleDerivedPath::Built & b) {
|
||||
error<EvalError>(
|
||||
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();
|
||||
|
@ -2512,7 +2513,7 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
|
|||
|
||||
case nThunk: // Must not be left by forceValue
|
||||
default:
|
||||
error<EvalError>("cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).debugThrow();
|
||||
errors.make<EvalError>("cannot compare %1% with %2%", showType(v1), showType(v2)).withTrace(pos, errorCtx).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2755,7 +2756,7 @@ SourcePath EvalState::findFile(const SearchPath & searchPath, const std::string_
|
|||
if (path.starts_with("nix/"))
|
||||
return CanonPath(concatStrings(corepkgsPrefix, path.substr(4)));
|
||||
|
||||
error<ThrownError>(
|
||||
errors.make<ThrownError>(
|
||||
evalSettings.pureEval
|
||||
? "cannot look up '<%s>' in pure evaluation mode (use '--impure' to override)"
|
||||
: "file '%s' was not found in the Nix search path (add it using $NIX_PATH or -I)",
|
||||
|
@ -2817,7 +2818,7 @@ std::optional<std::string> EvalState::resolveSearchPathPath(const SearchPath::Pa
|
|||
|
||||
std::string ExternalValueBase::coerceToString(EvalState & state, const PosIdx & pos, NixStringContext & context, bool copyMore, bool copyToStore) const
|
||||
{
|
||||
state.error<TypeError>(
|
||||
state.errors.make<TypeError>(
|
||||
"cannot coerce %1% to a string: %2%", showType(), *this
|
||||
).atPos(pos).debugThrow();
|
||||
}
|
||||
|
|
|
@ -348,6 +348,18 @@ struct EvalRuntimeCaches
|
|||
std::map<SourcePath, std::shared_ptr<CachedEvalFile>> fileEval;
|
||||
};
|
||||
|
||||
struct EvalErrorContext
|
||||
{
|
||||
const PosTable & positions;
|
||||
DebugState * debug;
|
||||
|
||||
template<class T, typename... Args>
|
||||
[[gnu::noinline]]
|
||||
EvalErrorBuilder<T> make(const Args & ... args) {
|
||||
return EvalErrorBuilder<T>(positions, debug, args...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class EvalState
|
||||
{
|
||||
|
@ -389,12 +401,7 @@ public:
|
|||
const ref<Store> buildStore;
|
||||
|
||||
std::unique_ptr<DebugState> debug;
|
||||
|
||||
template<class T, typename... Args>
|
||||
[[gnu::noinline]]
|
||||
EvalErrorBuilder<T> error(const Args & ... args) {
|
||||
return EvalErrorBuilder<T>(*this, args...);
|
||||
}
|
||||
EvalErrorContext errors;
|
||||
|
||||
private:
|
||||
|
||||
|
|
|
@ -142,14 +142,14 @@ static FlakeInput parseFlakeInput(EvalState & state,
|
|||
auto intValue = attr.value->integer.value;
|
||||
|
||||
if (intValue < 0) {
|
||||
state.error<EvalError>("negative value given for flake input attribute %1%: %2%", state.symbols[attr.name], intValue).debugThrow();
|
||||
state.errors.make<EvalError>("negative value given for flake input attribute %1%: %2%", state.symbols[attr.name], intValue).debugThrow();
|
||||
}
|
||||
uint64_t asUnsigned = intValue;
|
||||
attrs.emplace(state.symbols[attr.name], asUnsigned);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
state.error<TypeError>("flake input attribute '%s' is %s while a string, Boolean, or integer is expected",
|
||||
state.errors.make<TypeError>("flake input attribute '%s' is %s while a string, Boolean, or integer is expected",
|
||||
state.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.error<EvalError>("file '%s' must be an attribute set", resolvedFlakeFile).debugThrow();
|
||||
state.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.error<TypeError>("list element in flake configuration setting '%s' is %s while a string is expected",
|
||||
state.errors.make<TypeError>("list element in flake configuration setting '%s' is %s while a string is expected",
|
||||
state.symbols[setting.name], showType(*setting.value)).debugThrow();
|
||||
ss.emplace_back(state.forceStringNoCtx(*elem, setting.pos, ""));
|
||||
}
|
||||
flake.config.settings.emplace(state.symbols[setting.name], ss);
|
||||
}
|
||||
else
|
||||
state.error<TypeError>("flake configuration setting '%s' is %s",
|
||||
state.errors.make<TypeError>("flake configuration setting '%s' is %s",
|
||||
state.symbols[setting.name], showType(*setting.value)).debugThrow();
|
||||
}
|
||||
}
|
||||
|
@ -858,7 +858,7 @@ void prim_flakeRefToString(
|
|||
auto intValue = attr.value->integer.value;
|
||||
|
||||
if (intValue < 0) {
|
||||
state.error<EvalError>("negative value given for flake ref attr %1%: %2%", state.symbols[attr.name], intValue).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("negative value given for flake ref attr %1%: %2%", state.symbols[attr.name], intValue).atPos(pos).debugThrow();
|
||||
}
|
||||
uint64_t asUnsigned = intValue;
|
||||
|
||||
|
@ -870,7 +870,7 @@ void prim_flakeRefToString(
|
|||
attrs.emplace(state.symbols[attr.name],
|
||||
std::string(attr.value->str()));
|
||||
} else {
|
||||
state.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"flake reference attribute sets may only contain integers, Booleans, "
|
||||
"and strings, but attribute '%s' is %s",
|
||||
state.symbols[attr.name],
|
||||
|
|
|
@ -50,7 +50,7 @@ std::string DrvInfo::queryName()
|
|||
{
|
||||
if (name == "" && attrs) {
|
||||
auto i = attrs->find(state->s.name);
|
||||
if (i == attrs->end()) state->error<TypeError>("derivation name missing").debugThrow();
|
||||
if (i == attrs->end()) state->errors.make<TypeError>("derivation name missing").debugThrow();
|
||||
name = state->forceStringNoCtx(*i->value, noPos, "while evaluating the 'name' attribute of a derivation");
|
||||
}
|
||||
return name;
|
||||
|
@ -446,7 +446,7 @@ static void getDerivations(EvalState & state, Value & vIn,
|
|||
|
||||
return;
|
||||
} else if (v.type() != nAttrs) {
|
||||
state.error<TypeError>(
|
||||
state.errors.make<TypeError>(
|
||||
"expression was expected to be a derivation or collection of derivations, but instead was %s",
|
||||
showType(v.type(), true)
|
||||
).debugThrow();
|
||||
|
|
|
@ -364,7 +364,7 @@ void ExprVar::bindVars(EvalState & es, const std::shared_ptr<const StaticEnv> &
|
|||
enclosing `with'. If there is no `with', then we can issue an
|
||||
"undefined variable" error now. */
|
||||
if (withLevel == -1)
|
||||
es.error<UndefinedVarError>(
|
||||
es.errors.make<UndefinedVarError>(
|
||||
"undefined variable '%1%'",
|
||||
es.symbols[name]
|
||||
).atPos(pos).debugThrow();
|
||||
|
|
|
@ -47,7 +47,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context)
|
|||
for (auto & c : context) {
|
||||
auto ensureValid = [&](const StorePath & p) {
|
||||
if (!store->isValidPath(p))
|
||||
error<InvalidPathError>(store->printStorePath(p)).debugThrow();
|
||||
errors.make<InvalidPathError>(store->printStorePath(p)).debugThrow();
|
||||
};
|
||||
std::visit(overloaded {
|
||||
[&](const NixStringContextElem::Built & b) {
|
||||
|
@ -74,7 +74,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context)
|
|||
if (drvs.empty()) return {};
|
||||
|
||||
if (!evalSettings.enableImportFromDerivation)
|
||||
error<EvalError>(
|
||||
errors.make<EvalError>(
|
||||
"cannot build '%1%' during evaluation because the option 'allow-import-from-derivation' is disabled",
|
||||
drvs.begin()->to_string(*store)
|
||||
).debugThrow();
|
||||
|
@ -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.error<EvalError>("could not open '%1%': %2%", path, dlerror()).debugThrow();
|
||||
state.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.error<EvalError>("could not load symbol '%1%' from '%2%': %3%", sym, path, message).debugThrow();
|
||||
state.errors.make<EvalError>("could not load symbol '%1%' from '%2%': %3%", sym, path, message).debugThrow();
|
||||
else
|
||||
state.error<EvalError>("symbol '%1%' from '%2%' resolved to NULL when a function pointer was expected", sym, path).debugThrow();
|
||||
state.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.error<EvalError>("at least one argument to 'exec' required").atPos(pos).debugThrow();
|
||||
state.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.error<EvalError>("cannot compare %s with %s", showType(*v1), showType(*v2)).debugThrow();
|
||||
state.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.error<EvalError>("cannot compare %s with %s; values of that type are incomparable", showType(*v1), showType(*v2)).debugThrow();
|
||||
state.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.error<TypeError>("attribute '%s' missing", state.symbols[attrSym]).withTrace(noPos, errorCtx).debugThrow();
|
||||
state.errors.make<TypeError>("attribute '%s' missing", state.symbols[attrSym]).withTrace(noPos, errorCtx).debugThrow();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@ -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.error<Abort>("evaluation aborted with the following error message: '%1%'", s).debugThrow();
|
||||
state.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.error<ThrownError>(s).debugThrow();
|
||||
state.errors.make<ThrownError>(s).debugThrow();
|
||||
}
|
||||
|
||||
static void prim_addErrorContext(EvalState & state, const PosIdx pos, Value * * args, Value & v)
|
||||
|
@ -827,7 +827,7 @@ drvName, Bindings * attrs, Value & v)
|
|||
experimentalFeatureSettings.require(Xp::DynamicDerivations);
|
||||
ingestionMethod = TextIngestionMethod {};
|
||||
} else
|
||||
state.error<EvalError>(
|
||||
state.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.error<EvalError>("duplicate derivation output '%1%'", j)
|
||||
state.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.error<EvalError>("invalid derivation output name 'drv'")
|
||||
state.errors.make<EvalError>("invalid derivation output name 'drv'")
|
||||
.atPos(v)
|
||||
.debugThrow();
|
||||
outputs.insert(j);
|
||||
}
|
||||
if (outputs.empty())
|
||||
state.error<EvalError>("derivation cannot have an empty set of outputs")
|
||||
state.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.error<EvalError>("required attribute 'builder' missing")
|
||||
state.errors.make<EvalError>("required attribute 'builder' missing")
|
||||
.atPos(v)
|
||||
.debugThrow();
|
||||
|
||||
if (drv.platform == "")
|
||||
state.error<EvalError>("required attribute 'system' missing")
|
||||
state.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.error<EvalError>(
|
||||
state.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.error<EvalError>(
|
||||
state.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.error<EvalError>("derivation cannot be both content-addressed and impure")
|
||||
state.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.error<AssertionError>(
|
||||
state.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.error<EvalError>(
|
||||
state.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.error<EvalError>("path '%1%' is not in the Nix store", path)
|
||||
state.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)
|
||||
|
@ -1257,7 +1257,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.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"the contents of the file '%1%' cannot be represented as a Nix string",
|
||||
path
|
||||
).atPos(pos).debugThrow();
|
||||
|
@ -1308,7 +1308,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
|
|||
auto rewrites = state.realiseContext(context);
|
||||
path = rewriteStrings(path, rewrites);
|
||||
} catch (InvalidPathError & e) {
|
||||
state.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"cannot find '%1%', since path '%2%' is not valid",
|
||||
path,
|
||||
e.path
|
||||
|
@ -1332,7 +1332,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.error<EvalError>("unknown hash type '%1%'", type).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("unknown hash type '%1%'", type).atPos(pos).debugThrow();
|
||||
|
||||
auto path = realisePath(state, pos, *args[1]);
|
||||
|
||||
|
@ -1461,7 +1461,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.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"files created by %1% may not reference derivations, but %2% references %3%",
|
||||
"builtins.toFile",
|
||||
name,
|
||||
|
@ -1548,7 +1548,7 @@ static void addPath(
|
|||
auto dstPath = fetchToStore(
|
||||
*state.store, CanonPath(path), name, method, &filter, state.repair);
|
||||
if (expectedHash && expectedStorePath != dstPath)
|
||||
state.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"store path mismatch in (possibly filtered) path added from '%s'",
|
||||
path
|
||||
).atPos(pos).debugThrow();
|
||||
|
@ -1595,13 +1595,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.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"unsupported argument '%1%' to 'addPath'",
|
||||
state.symbols[attr.name]
|
||||
).atPos(attr.pos).debugThrow();
|
||||
}
|
||||
if (!path)
|
||||
state.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"missing required 'path' attribute in the first argument to builtins.path"
|
||||
).atPos(pos).debugThrow();
|
||||
if (name.empty())
|
||||
|
@ -1908,7 +1908,7 @@ static void prim_functionArgs(EvalState & state, const PosIdx pos, Value * * arg
|
|||
return;
|
||||
}
|
||||
if (!args[0]->isLambda())
|
||||
state.error<TypeError>("'functionArgs' requires a function").atPos(pos).debugThrow();
|
||||
state.errors.make<TypeError>("'functionArgs' requires a function").atPos(pos).debugThrow();
|
||||
|
||||
if (!args[0]->lambda.fun->hasFormals()) {
|
||||
v.mkAttrs(&Bindings::EMPTY);
|
||||
|
@ -2005,7 +2005,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.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"list index %1% is out of bounds",
|
||||
n
|
||||
).atPos(pos).debugThrow();
|
||||
|
@ -2033,7 +2033,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.error<EvalError>("'tail' called on an empty list").atPos(pos).debugThrow();
|
||||
state.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)
|
||||
|
@ -2180,7 +2180,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.error<EvalError>("cannot create list of size %1%", len_).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("cannot create list of size %1%", len_).atPos(pos).debugThrow();
|
||||
|
||||
size_t len = len_;
|
||||
|
||||
|
@ -2353,7 +2353,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.error<EvalError>("integer overflow in adding %1% + %2%", i1, i2).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("integer overflow in adding %1% + %2%", i1, i2).atPos(pos).debugThrow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2374,7 +2374,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.error<EvalError>("integer overflow in subtracting %1% - %2%", i1, i2).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("integer overflow in subtracting %1% - %2%", i1, i2).atPos(pos).debugThrow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2395,7 +2395,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.error<EvalError>("integer overflow in multiplying %1% * %2%", i1, i2).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("integer overflow in multiplying %1% * %2%", i1, i2).atPos(pos).debugThrow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2407,7 +2407,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.error<EvalError>("division by zero").atPos(pos).debugThrow();
|
||||
state.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);
|
||||
|
@ -2419,7 +2419,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.error<EvalError>("integer overflow in dividing %1% / %2%", i1, i2).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("integer overflow in dividing %1% / %2%", i1, i2).atPos(pos).debugThrow();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2483,7 +2483,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.error<EvalError>("negative start position in 'substring'").atPos(pos).debugThrow();
|
||||
state.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;
|
||||
|
@ -2523,7 +2523,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.error<EvalError>("unknown hash algorithm '%1%'", type).atPos(pos).debugThrow();
|
||||
state.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");
|
||||
|
@ -2585,11 +2585,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.error<EvalError>("memory limit exceeded by regular expression '%s'", re)
|
||||
state.errors.make<EvalError>("memory limit exceeded by regular expression '%s'", re)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
} else
|
||||
state.error<EvalError>("invalid regular expression '%s'", re)
|
||||
state.errors.make<EvalError>("invalid regular expression '%s'", re)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
}
|
||||
|
@ -2651,11 +2651,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.error<EvalError>("memory limit exceeded by regular expression '%s'", re)
|
||||
state.errors.make<EvalError>("memory limit exceeded by regular expression '%s'", re)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
} else
|
||||
state.error<EvalError>("invalid regular expression '%s'", re)
|
||||
state.errors.make<EvalError>("invalid regular expression '%s'", re)
|
||||
.atPos(pos)
|
||||
.debugThrow();
|
||||
}
|
||||
|
@ -2685,7 +2685,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.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"'from' and 'to' arguments passed to builtins.replaceStrings have different lengths"
|
||||
).atPos(pos).debugThrow();
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, Value *
|
|||
|
||||
auto contextSize = context.size();
|
||||
if (contextSize != 1) {
|
||||
state.error<EvalError>(
|
||||
state.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.error<EvalError>(
|
||||
state.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.error<EvalError>(
|
||||
state.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.symbols[i.name];
|
||||
if (!state.store->isStorePath(name))
|
||||
state.error<EvalError>(
|
||||
state.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.error<EvalError>(
|
||||
state.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.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"tried to add derivation output context of %s, which is not a derivation, to a string",
|
||||
name
|
||||
).atPos(i.pos).debugThrow();
|
||||
|
|
|
@ -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.error<EvalError>("unsupported argument '%s' to 'fetchMercurial'", state.symbols[attr.name]).atPos(attr.pos).debugThrow();
|
||||
state.errors.make<EvalError>("unsupported argument '%s' to 'fetchMercurial'", state.symbols[attr.name]).atPos(attr.pos).debugThrow();
|
||||
}
|
||||
|
||||
if (url.empty())
|
||||
state.error<EvalError>("'url' argument required").atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("'url' argument required").atPos(pos).debugThrow();
|
||||
|
||||
} else
|
||||
url = state.coerceToString(pos, *args[0], context,
|
||||
|
|
|
@ -124,12 +124,12 @@ static void fetchTree(
|
|||
|
||||
if (auto aType = args[0]->attrs->get(state.s.type)) {
|
||||
if (type)
|
||||
state.error<EvalError>(
|
||||
state.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.error<EvalError>(
|
||||
state.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.error<EvalError>("negative value given for fetchTree attr %1%: %2%", state.symbols[attr.name], intValue).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("negative value given for fetchTree attr %1%: %2%", state.symbols[attr.name], intValue).atPos(pos).debugThrow();
|
||||
}
|
||||
unsigned long asUnsigned = intValue;
|
||||
|
||||
attrs.emplace(state.symbols[attr.name], asUnsigned);
|
||||
} else
|
||||
state.error<TypeError>("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
|
||||
state.errors.make<TypeError>("fetchTree argument '%s' is %s while a string, Boolean or integer is expected",
|
||||
state.symbols[attr.name], showType(*attr.value)).debugThrow();
|
||||
}
|
||||
|
||||
if (!params.allowNameArgument)
|
||||
if (auto nameIter = attrs.find("name"); nameIter != attrs.end())
|
||||
state.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"attribute 'name' isn’t 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.error<EvalError>("in pure evaluation mode, 'fetchTree' requires a locked input").atPos(pos).debugThrow();
|
||||
state.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.error<EvalError>("unsupported argument '%s' to '%s'", n, who)
|
||||
state.errors.make<EvalError>("unsupported argument '%s' to '%s'", n, who)
|
||||
.atPos(pos).debugThrow();
|
||||
}
|
||||
|
||||
if (!url)
|
||||
state.error<EvalError>(
|
||||
state.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.error<EvalError>("in pure evaluation mode, '%s' requires a 'sha256' argument", who).atPos(pos).debugThrow();
|
||||
state.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.error<EvalError>(
|
||||
state.errors.make<EvalError>(
|
||||
"hash mismatch in file downloaded from '%s':\n specified: %s\n got: %s",
|
||||
*url,
|
||||
expectedHash->to_string(Base::Base32, true),
|
||||
|
|
|
@ -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.error<EvalError>("while parsing TOML: %s", e.what()).atPos(pos).debugThrow();
|
||||
state.errors.make<EvalError>("while parsing TOML: %s", e.what()).atPos(pos).debugThrow();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -99,7 +99,7 @@ json printValueAsJSON(EvalState & state, bool strict,
|
|||
|
||||
case nThunk:
|
||||
case nFunction:
|
||||
state.error<TypeError>(
|
||||
state.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.error<TypeError>("cannot convert %1% to JSON", showType())
|
||||
state.errors.make<TypeError>("cannot convert %1% to JSON", showType())
|
||||
.debugThrow();
|
||||
}
|
||||
|
||||
|
|
|
@ -330,7 +330,7 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
|||
* try {
|
||||
* e->eval(*this, env, v);
|
||||
* if (v.type() != nAttrs)
|
||||
* error<TypeError>("expected a set but found %1%", v);
|
||||
* errors.make<TypeError>("expected a set but found %1%", v);
|
||||
* } catch (Error & e) {
|
||||
* e.addTrace(pos, errorCtx);
|
||||
* throw;
|
||||
|
@ -344,7 +344,7 @@ std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool s
|
|||
* e->eval(*this, env, v);
|
||||
* try {
|
||||
* if (v.type() != nAttrs)
|
||||
* error<TypeError>("expected a set but found %1%", v);
|
||||
* errors.make<TypeError>("expected a set but found %1%", v);
|
||||
* } catch (Error & e) {
|
||||
* e.addTrace(pos, errorCtx);
|
||||
* throw;
|
||||
|
|
|
@ -106,7 +106,7 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption
|
|||
}
|
||||
}
|
||||
else
|
||||
state->error<TypeError>("value at '%s' is not a string or an attribute set", state->positions[pos]).debugThrow();
|
||||
state->errors.make<TypeError>("value at '%s' is not a string or an attribute set", state->positions[pos]).debugThrow();
|
||||
};
|
||||
|
||||
recurse(*v, pos, *writeTo);
|
||||
|
|
|
@ -868,7 +868,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand
|
|||
auto templateDir = templateDirAttr->getString();
|
||||
|
||||
if (!store->isInStore(templateDir))
|
||||
evalState->error<TypeError>(
|
||||
evalState->errors.make<TypeError>(
|
||||
"'%s' was not found in the Nix store\n"
|
||||
"If you've set '%s' to a string, try using a path instead.",
|
||||
templateDir, templateDirAttr->getAttrPathStr()).debugThrow();
|
||||
|
@ -1374,7 +1374,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
|||
{
|
||||
auto aType = visitor.maybeGetAttr("type");
|
||||
if (!aType || aType->getString() != "app")
|
||||
state->error<EvalError>("not an app definition").debugThrow();
|
||||
state->errors.make<EvalError>("not an app definition").debugThrow();
|
||||
if (json) {
|
||||
j.emplace("type", "app");
|
||||
} else {
|
||||
|
|
|
@ -12,19 +12,19 @@ namespace nix {
|
|||
|
||||
TEST_F(ErrorTraceTest, TraceBuilder) {
|
||||
ASSERT_THROW(
|
||||
state.error<EvalError>("puppy").debugThrow(),
|
||||
state.errors.make<EvalError>("puppy").debugThrow(),
|
||||
EvalError
|
||||
);
|
||||
|
||||
ASSERT_THROW(
|
||||
state.error<EvalError>("puppy").withTrace(noPos, "doggy").debugThrow(),
|
||||
state.errors.make<EvalError>("puppy").withTrace(noPos, "doggy").debugThrow(),
|
||||
EvalError
|
||||
);
|
||||
|
||||
ASSERT_THROW(
|
||||
try {
|
||||
try {
|
||||
state.error<EvalError>("puppy").withTrace(noPos, "doggy").debugThrow();
|
||||
state.errors.make<EvalError>("puppy").withTrace(noPos, "doggy").debugThrow();
|
||||
} catch (Error & e) {
|
||||
e.addTrace(state.positions[noPos], "beans");
|
||||
throw;
|
||||
|
@ -47,10 +47,10 @@ namespace nix {
|
|||
|
||||
TEST_F(ErrorTraceTest, NestedThrows) {
|
||||
try {
|
||||
state.error<EvalError>("puppy").withTrace(noPos, "doggy").debugThrow();
|
||||
state.errors.make<EvalError>("puppy").withTrace(noPos, "doggy").debugThrow();
|
||||
} catch (BaseError & e) {
|
||||
try {
|
||||
state.error<EvalError>("beans").debugThrow();
|
||||
state.errors.make<EvalError>("beans").debugThrow();
|
||||
} catch (Error & e2) {
|
||||
e.addTrace(state.positions[noPos], "beans2");
|
||||
//e2.addTrace(state.positions[noPos], "Something", "");
|
||||
|
|
Loading…
Reference in a new issue