diff --git a/lix/libcmd/repl.hh b/lix/libcmd/repl.hh index 0e24ba573..1a04bc5b9 100644 --- a/lix/libcmd/repl.hh +++ b/lix/libcmd/repl.hh @@ -2,10 +2,11 @@ ///@file #include "lix/libexpr/eval.hh" +#include "lix/libutil/types.hh" namespace nix { -struct AbstractNixRepl +struct AbstractNixRepl : NeverAsync { typedef std::vector> AnnotatedValues; diff --git a/lix/libexpr/eval-error.cc b/lix/libexpr/eval-error.cc index 62165ff4b..c8254a7be 100644 --- a/lix/libexpr/eval-error.cc +++ b/lix/libexpr/eval-error.cc @@ -1,6 +1,7 @@ #include "lix/libexpr/eval-error.hh" #include "lix/libexpr/eval.hh" #include "lix/libexpr/value.hh" +#include "lix/libutil/types.hh" namespace nix { @@ -72,7 +73,7 @@ EvalErrorBuilder::addTrace(PosIdx pos, std::string_view formatString, const A } template -void EvalErrorBuilder::debugThrow() && +void EvalErrorBuilder::debugThrow(NeverAsync) && { if (debug) { if (auto last = debug->traces().next()) { diff --git a/lix/libexpr/eval-error.hh b/lix/libexpr/eval-error.hh index 8e1a7c25e..2d010293c 100644 --- a/lix/libexpr/eval-error.hh +++ b/lix/libexpr/eval-error.hh @@ -91,7 +91,7 @@ public: /** * Throw the underlying exception, invoking the debug state callback. */ - [[gnu::noinline, gnu::noreturn]] void debugThrow() &&; + [[gnu::noinline, gnu::noreturn]] void debugThrow(NeverAsync = {}) &&; /** * Throw the underlying exception, bypassing the debug state callback. diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index 95ba6023f..490759924 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -1,5 +1,6 @@ #include "lix/libexpr/eval.hh" #include "lix/libexpr/eval-settings.hh" +#include "lix/libstore/path.hh" #include "lix/libutil/archive.hh" #include "lix/libutil/ansicolor.hh" #include "lix/libutil/async.hh" @@ -337,7 +338,7 @@ Evaluator::Evaluator( debugRepl ? std::make_unique( positions, symbols, - [this, debugRepl](const ValMap & extraEnv) { + [this, debugRepl](const ValMap & extraEnv, NeverAsync) { return activeEval ? debugRepl(*activeEval, extraEnv) : ReplExitStatus::Continue; @@ -731,7 +732,9 @@ public: } }; -void DebugState::onEvalError(const EvalError * error, const Env & env, const Expr & expr) +void DebugState::onEvalError( + const EvalError * error, const Env & env, const Expr & expr, NeverAsync +) { // Make sure we have a debugger to run and we're not already in a debugger. if (inDebugger) @@ -765,7 +768,7 @@ void DebugState::onEvalError(const EvalError * error, const Env & env, const Exp if (se) { auto vm = mapStaticEnvBindings(symbols, *se.get(), env); DebuggerGuard _guard(inDebugger); - auto exitStatus = errorCallback(*vm); + auto exitStatus = errorCallback(*vm, {}); switch (exitStatus) { case ReplExitStatus::QuitAll: if (error) @@ -2458,7 +2461,7 @@ std::pair EvalState::coerceToSingleDerivedP [&](NixStringContextElem::DrvDeep &&) -> SingleDerivedPath { ctx.errors.make( "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(); + s).withTrace(pos, errorCtx).debugThrow(always_progresses); }, [&](NixStringContextElem::Built && b) -> SingleDerivedPath { return std::move(b); @@ -2484,13 +2487,13 @@ SingleDerivedPath EvalState::coerceToSingleDerivedPath(const PosIdx pos, Value & ctx.errors.make( "path string '%s' has context with the different path '%s'", s, sExpected) - .withTrace(pos, errorCtx).debugThrow(); + .withTrace(pos, errorCtx).debugThrow(always_progresses); }, [&](const SingleDerivedPath::Built & b) { ctx.errors.make( "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(*ctx.store), sExpected) - .withTrace(pos, errorCtx).debugThrow(); + .withTrace(pos, errorCtx).debugThrow(always_progresses); } }, derivedPath.raw()); } diff --git a/lix/libexpr/eval.hh b/lix/libexpr/eval.hh index de8d715dd..5b70fcbcb 100644 --- a/lix/libexpr/eval.hh +++ b/lix/libexpr/eval.hh @@ -7,6 +7,7 @@ #include "lix/libutil/box_ptr.hh" #include "lix/libutil/generator.hh" #include "lix/libutil/async.hh" +#include "lix/libutil/source-path.hh" #include "lix/libutil/types.hh" #include "lix/libexpr/value.hh" #include "lix/libexpr/nixexpr.hh" @@ -149,7 +150,7 @@ private: const SymbolTable & symbols; public: - std::function errorCallback; + std::function errorCallback; bool stop = false; bool inDebugger = false; std::map> exprEnvs; @@ -158,7 +159,7 @@ public: explicit DebugState( const PosTable & positions, const SymbolTable & symbols, - std::function errorCallback + std::function errorCallback ) : positions(positions) , symbols(symbols) @@ -167,7 +168,7 @@ public: assert(errorCallback); } - void onEvalError(const EvalError * error, const Env & env, const Expr & expr); + void onEvalError(const EvalError * error, const Env & env, const Expr & expr, NeverAsync = {}); const std::shared_ptr staticEnvFor(const Expr & expr) const { @@ -469,7 +470,7 @@ public: overloaded{ [](T & p) -> T { return std::move(p); }, [](EvalErrorBuilder & e) -> T { - std::move(e).debugThrow(); + std::move(e).debugThrow(always_progresses); } }, static_cast> &>(*this) diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index be6b7baf1..21265f7f3 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -19,6 +19,7 @@ #include "lix/libexpr/primops.hh" #include "lix/libfetchers/fetch-to-store.hh" #include "lix/libutil/result.hh" +#include "lix/libutil/types.hh" #include #include @@ -50,7 +51,7 @@ StringMap EvalState::realiseContext(const NixStringContext & context) for (auto & c : context) { auto ensureValid = [&](const StorePath & p) { if (!aio.blockOn(ctx.store->isValidPath(p))) - ctx.errors.make(ctx.store->printStorePath(p)).debugThrow(); + ctx.errors.make(ctx.store->printStorePath(p)).debugThrow(always_progresses); }; std::visit(overloaded { [&](const NixStringContextElem::Built & b) { @@ -432,7 +433,7 @@ template } } -struct CompareValues +struct CompareValues : NeverAsync { EvalState & state; const PosIdx pos; @@ -827,7 +828,7 @@ drvName, Bindings * attrs, Value & v) const std::string & key = state.ctx.symbols[i->name]; vomit("processing attribute '%1%'", key); - auto handleHashMode = [&](const std::string_view s) { + auto handleHashMode = [&](const std::string_view s, NeverAsync = {}) { if (s == "recursive") ingestionMethod = FileIngestionMethod::Recursive; else if (s == "flat") ingestionMethod = FileIngestionMethod::Flat; else if (s == "text") { @@ -839,7 +840,7 @@ drvName, Bindings * attrs, Value & v) ).atPos(v).debugThrow(); }; - auto handleOutputs = [&](const Strings & ss) { + auto handleOutputs = [&](const Strings & ss, NeverAsync = {}) { outputs.clear(); for (auto & j : ss) { if (outputs.find(j) != outputs.end()) diff --git a/lix/libexpr/primops/context.cc b/lix/libexpr/primops/context.cc index a5038a0f2..603368501 100644 --- a/lix/libexpr/primops/context.cc +++ b/lix/libexpr/primops/context.cc @@ -3,6 +3,7 @@ #include "lix/libexpr/extra-primops.hh" #include "lix/libstore/derivations.hh" #include "lix/libstore/store-api.hh" +#include "lix/libutil/types.hh" namespace nix { @@ -69,7 +70,7 @@ void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, Value * state.ctx.errors.make( "path '%s' is not a derivation", state.ctx.store->printStorePath(c.path) - ).atPos(pos).debugThrow(); + ).atPos(pos).debugThrow(always_progresses); } return NixStringContextElem::DrvDeep { .drvPath = c.path, @@ -79,7 +80,7 @@ void prim_addDrvOutputDependencies(EvalState & state, const PosIdx pos, Value * state.ctx.errors.make( "`addDrvOutputDependencies` can only act on derivations, not on a derivation output such as '%1%'", c.output - ).atPos(pos).debugThrow(); + ).atPos(pos).debugThrow(always_progresses); }, [&](const NixStringContextElem::DrvDeep & c) -> NixStringContextElem::DrvDeep { /* Reuse original item because we want this to be idempotent. */ diff --git a/lix/nix/eval.cc b/lix/nix/eval.cc index 25ebcbe25..60b41823f 100644 --- a/lix/nix/eval.cc +++ b/lix/nix/eval.cc @@ -7,6 +7,7 @@ #include "lix/libexpr/eval-inline.hh" #include "lix/libexpr/value-to-json.hh" #include "eval.hh" +#include "lix/libutil/types.hh" namespace nix { @@ -80,9 +81,9 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption if (pathExists(*writeTo)) throw Error("path '%s' already exists", *writeTo); - std::function recurse; + std::function recurse; - recurse = [&](Value & v, const PosIdx pos, const Path & path) + recurse = [&](Value & v, const PosIdx pos, const Path & path, NeverAsync) { state->forceValue(v, pos); if (v.type() == nString) @@ -96,7 +97,7 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption try { if (name == "." || name == "..") throw Error("invalid file name '%s'", name); - recurse(*attr.value, attr.pos, concatStrings(path, "/", name)); + recurse(*attr.value, attr.pos, concatStrings(path, "/", name), {}); } catch (Error & e) { e.addTrace( evaluator->positions[attr.pos], @@ -109,7 +110,7 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption evaluator->errors.make("value at '%s' is not a string or an attribute set", evaluator->positions[pos]).debugThrow(); }; - recurse(*v, pos, *writeTo); + recurse(*v, pos, *writeTo, {}); } else if (raw) { diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index 7884bc8ad..65d0c138b 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -19,6 +19,7 @@ #include "lix/libutil/terminal.hh" #include "lix/libutil/signals.hh" #include "flake.hh" +#include "lix/libutil/types.hh" #include #include @@ -1194,13 +1195,15 @@ struct CmdFlakeShow : FlakeCommand, MixJSON eval_cache::AttrCursor & visitor, const std::vector & attrPath, const std::string & headerPrefix, - const std::string & nextPrefix)> visit; + const std::string & nextPrefix, + NeverAsync)> visit; visit = [&]( eval_cache::AttrCursor & visitor, const std::vector & attrPath, const std::string & headerPrefix, - const std::string & nextPrefix) + const std::string & nextPrefix, + NeverAsync) -> JSON { auto j = JSON::object(); @@ -1209,7 +1212,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON fmt("evaluating '%s'", concatStringsSep(".", attrPath))); try { - auto recurse = [&]() + auto recurse = [&](NeverAsync = {}) { if (!json) logger->cout("%s", headerPrefix); @@ -1226,12 +1229,12 @@ struct CmdFlakeShow : FlakeCommand, MixJSON attrPath2.push_back(attr); auto j2 = visit(*visitor2, attrPath2, fmt(ANSI_GREEN "%s%s" ANSI_NORMAL ANSI_BOLD "%s" ANSI_NORMAL, nextPrefix, last ? treeLast : treeConn, attr), - nextPrefix + (last ? treeNull : treeLine)); + nextPrefix + (last ? treeNull : treeLine), {}); if (json) j.emplace(attr, std::move(j2)); } }; - auto showDerivation = [&]() + auto showDerivation = [&](NeverAsync = {}) { auto name = visitor.getAttr(*state, "name")->getString(*state); std::optional description; @@ -1410,7 +1413,7 @@ struct CmdFlakeShow : FlakeCommand, MixJSON auto cache = openEvalCache(*evaluator, flake); - auto j = visit(*cache->getRoot(), {}, fmt(ANSI_BOLD "%s" ANSI_NORMAL, flake->flake.lockedRef), ""); + auto j = visit(*cache->getRoot(), {}, fmt(ANSI_BOLD "%s" ANSI_NORMAL, flake->flake.lockedRef), "", {}); if (json) logger->cout("%s", j.dump()); } diff --git a/subprojects/nix-eval-jobs/src/worker.cc b/subprojects/nix-eval-jobs/src/worker.cc index feaef7955..7fd66155d 100644 --- a/subprojects/nix-eval-jobs/src/worker.cc +++ b/subprojects/nix-eval-jobs/src/worker.cc @@ -89,7 +89,7 @@ readConstituents(const nix::Value *v, nix::box_ptr &state, state->ctx.errors .make("derivation must have a ‘constituents’ " "attribute") - .debugThrow(); + .debugThrow(nix::always_progresses); // we can't have a debugger here nix::NixStringContext context; state->coerceToString(a->pos, *a->value, context, diff --git a/tests/unit/libcmd/args.cc b/tests/unit/libcmd/args.cc index 3fd98cdc4..a9c0f4ed4 100644 --- a/tests/unit/libcmd/args.cc +++ b/tests/unit/libcmd/args.cc @@ -10,6 +10,7 @@ #include "lix/libstore/filetransfer.hh" #include "lix/libmain/shared.hh" #include "lix/libstore/store-api.hh" +#include "lix/libutil/types.hh" constexpr std::string_view INVALID_CHANNEL = "channel:example"; constexpr std::string_view CHANNEL_URL = "https://nixos.org/channels/example/nixexprs.tar.xz"; diff --git a/tests/unit/libexpr/error_traces.cc b/tests/unit/libexpr/error_traces.cc index 6b98c9014..2d2b2acc1 100644 --- a/tests/unit/libexpr/error_traces.cc +++ b/tests/unit/libexpr/error_traces.cc @@ -1,6 +1,7 @@ #include #include +#include "lix/libutil/types.hh" #include "tests/libexpr.hh" namespace nix { @@ -12,19 +13,23 @@ namespace nix { TEST_F(ErrorTraceTest, TraceBuilder) { ASSERT_THROW( - evaluator.errors.make("puppy").debugThrow(), + evaluator.errors.make("puppy").debugThrow(always_progresses), EvalError ); ASSERT_THROW( - evaluator.errors.make("puppy").withTrace(noPos, "doggy").debugThrow(), + evaluator.errors.make("puppy") + .withTrace(noPos, "doggy") + .debugThrow(always_progresses), EvalError ); ASSERT_THROW( try { try { - evaluator.errors.make("puppy").withTrace(noPos, "doggy").debugThrow(); + evaluator.errors.make("puppy") + .withTrace(noPos, "doggy") + .debugThrow(always_progresses); } catch (Error & e) { e.addTrace(evaluator.positions[noPos], "beans"); throw; @@ -47,10 +52,12 @@ namespace nix { TEST_F(ErrorTraceTest, NestedThrows) { try { - evaluator.errors.make("puppy").withTrace(noPos, "doggy").debugThrow(); + evaluator.errors.make("puppy") + .withTrace(noPos, "doggy") + .debugThrow(always_progresses); } catch (BaseError & e) { try { - evaluator.errors.make("beans").debugThrow(); + evaluator.errors.make("beans").debugThrow(always_progresses); } catch (Error & e2) { e.addTrace(evaluator.positions[noPos], "beans2"); //e2.addTrace(state.positions[noPos], "Something", "");