From db35aa753b87a8875eaf26d07d77f30c00208b9e Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Sun, 28 Sep 2025 00:02:21 +0200 Subject: [PATCH] libexpr: de-ptr-ize many Value uses with thunk state being shareable we no longer need to worry about value uniqueness, only about value lifetime. this means we can liberally drop indirections and allocations, passing references instead of pointers or using stack memory instead of gc-managed memory for some intermediates. Change-Id: I2d48a6fd57a376d544bd9bd2d05e5420611986d1 --- lix/legacy/nix-build.cc | 12 +-- lix/legacy/nix-env.cc | 6 +- lix/legacy/nix-instantiate.cc | 2 +- lix/libcmd/installable-attr-path.cc | 20 ++--- lix/libcmd/installable-attr-path.hh | 12 +-- lix/libcmd/installable-flake.cc | 4 +- lix/libcmd/installable-flake.hh | 2 +- lix/libcmd/installable-value.cc | 5 +- lix/libcmd/installable-value.hh | 2 +- lix/libcmd/installables.cc | 20 +++-- lix/libcmd/repl.cc | 2 +- lix/libcmd/repl.hh | 2 +- lix/libexpr/attr-path.cc | 46 +++++------ lix/libexpr/attr-path.hh | 8 +- lix/libexpr/eval-cache.cc | 11 +-- lix/libexpr/eval-cache.hh | 4 +- lix/libexpr/eval.cc | 55 ++++++------- lix/libexpr/flake/flake.cc | 44 +++++++---- lix/libexpr/get-drvs.cc | 5 +- lix/libexpr/get-drvs.hh | 2 +- lix/libexpr/json-to-value.cc | 63 ++++++++------- lix/libexpr/nixexpr.hh | 9 ++- lix/libexpr/primops.cc | 101 +++++++++++++++--------- lix/libexpr/value.hh | 5 +- lix/nix/bundle.cc | 14 ++-- lix/nix/edit.cc | 2 +- lix/nix/eval.cc | 21 +++-- lix/nix/flake.cc | 11 +-- lix/nix/main.cc | 24 +++--- lix/nix/prefetch.cc | 2 +- lix/nix/repl.cc | 8 +- lix/nix/upgrade-nix.cc | 10 ++- subprojects/nix-eval-jobs/src/worker.cc | 8 +- tests/unit/libexpr/attr-path.cc | 4 +- tests/unit/libexpr/derived-path.cc | 12 +-- 35 files changed, 311 insertions(+), 247 deletions(-) diff --git a/lix/legacy/nix-build.cc b/lix/legacy/nix-build.cc index 517ee8df2..2f8e675c7 100644 --- a/lix/legacy/nix-build.cc +++ b/lix/legacy/nix-build.cc @@ -285,12 +285,12 @@ static void main_nix_build(AsyncIoRoot & aio, std::string programName, Strings a }; for (auto & i : attrPaths) { - Value & v(*findAlongAttrPath( - *state, - i, - takesNixShellAttr(vRoot) ? *autoArgsWithInNixShell : *autoArgs, - vRoot - ).first); + Value v( + findAlongAttrPath( + *state, i, takesNixShellAttr(vRoot) ? *autoArgsWithInNixShell : *autoArgs, vRoot + ) + .first + ); state->forceValue(v, noPos); getDerivations( *state, diff --git a/lix/legacy/nix-env.cc b/lix/legacy/nix-env.cc index f59159f05..e72c9171e 100644 --- a/lix/legacy/nix-env.cc +++ b/lix/legacy/nix-env.cc @@ -200,7 +200,7 @@ static void loadDerivations(EvalState & state, const SourcePath & nixExprPath, Value vRoot; loadSourceExpr(state, nixExprPath, vRoot); - Value & v(*findAlongAttrPath(state, pathPrefix, autoArgs, vRoot).first); + Value v(findAlongAttrPath(state, pathPrefix, autoArgs, vRoot).first); getDerivations(state, v, pathPrefix, autoArgs, elems, true); @@ -482,7 +482,7 @@ static void queryInstSources(EvalState & state, Value vRoot; loadSourceExpr(state, *instSource.nixExprPath, vRoot); for (auto & i : args) { - Value & v(*findAlongAttrPath(state, i, *instSource.autoArgs, vRoot).first); + Value v(findAlongAttrPath(state, i, *instSource.autoArgs, vRoot).first); getDerivations(state, v, "", *instSource.autoArgs, elems, true); } break; @@ -519,7 +519,7 @@ static void setMetaFlag(EvalState & state, DrvInfo & drv, { auto v = state.ctx.mem.allocValue(); v->mkString(value); - drv.setMeta(state, name, v); + drv.setMeta(state, name, *v); } static void installDerivations(Globals & globals, diff --git a/lix/legacy/nix-instantiate.cc b/lix/legacy/nix-instantiate.cc index 8f97c814d..ab46e3ec3 100644 --- a/lix/legacy/nix-instantiate.cc +++ b/lix/legacy/nix-instantiate.cc @@ -38,7 +38,7 @@ void processExpr(EvalState & state, const Strings & attrPaths, state.eval(e, vRoot); for (auto & i : attrPaths) { - Value & v(*findAlongAttrPath(state, i, autoArgs, vRoot).first); + Value v(findAlongAttrPath(state, i, autoArgs, vRoot).first); state.forceValue(v, noPos); NixStringContext context; diff --git a/lix/libcmd/installable-attr-path.cc b/lix/libcmd/installable-attr-path.cc index cb9fb40f3..72db441e9 100644 --- a/lix/libcmd/installable-attr-path.cc +++ b/lix/libcmd/installable-attr-path.cc @@ -12,9 +12,10 @@ namespace nix { InstallableAttrPath::InstallableAttrPath( ref state, SourceExprCommand & cmd, - Value * v, + Value & v, const std::string & attrPath, - ExtendedOutputsSpec extendedOutputsSpec) + ExtendedOutputsSpec extendedOutputsSpec +) : InstallableValue(state) , cmd(cmd) , v(allocRootValue(v)) @@ -22,10 +23,10 @@ InstallableAttrPath::InstallableAttrPath( , extendedOutputsSpec(std::move(extendedOutputsSpec)) { } -std::pair InstallableAttrPath::toValue(EvalState & state) +std::pair InstallableAttrPath::toValue(EvalState & state) { - auto [vRes, pos] = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(*evaluator), **v); - state.forceValue(*vRes, pos); + auto [vRes, pos] = findAlongAttrPath(state, attrPath, *cmd.getAutoArgs(*evaluator), *v); + state.forceValue(vRes, pos); return {vRes, pos}; } @@ -34,7 +35,7 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths(EvalState & state) auto [v, pos] = toValue(state); if (std::optional derivedPathWithInfo = trySinglePathToDerivedPaths( - state, *v, pos, fmt("while evaluating the attribute '%s'", attrPath) + state, v, pos, fmt("while evaluating the attribute '%s'", attrPath) )) { return { *derivedPathWithInfo }; @@ -43,7 +44,7 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths(EvalState & state) Bindings & autoArgs = *cmd.getAutoArgs(*evaluator); DrvInfos drvInfos; - getDerivations(state, *v, "", autoArgs, drvInfos, false); + getDerivations(state, v, "", autoArgs, drvInfos, false); // Backward compatibility hack: group results by drvPath. This // helps keep .all output together. @@ -92,9 +93,10 @@ DerivedPathsWithInfo InstallableAttrPath::toDerivedPaths(EvalState & state) InstallableAttrPath InstallableAttrPath::parse( ref state, SourceExprCommand & cmd, - Value * v, + Value & v, std::string_view prefix, - ExtendedOutputsSpec extendedOutputsSpec) + ExtendedOutputsSpec extendedOutputsSpec +) { return { state, cmd, v, diff --git a/lix/libcmd/installable-attr-path.hh b/lix/libcmd/installable-attr-path.hh index 3e50c92a2..07df4d205 100644 --- a/lix/libcmd/installable-attr-path.hh +++ b/lix/libcmd/installable-attr-path.hh @@ -20,13 +20,14 @@ class InstallableAttrPath : public InstallableValue InstallableAttrPath( ref state, SourceExprCommand & cmd, - Value * v, + Value & v, const std::string & attrPath, - ExtendedOutputsSpec extendedOutputsSpec); + ExtendedOutputsSpec extendedOutputsSpec + ); std::string what() const override { return attrPath; }; - std::pair toValue(EvalState & state) override; + std::pair toValue(EvalState & state) override; DerivedPathsWithInfo toDerivedPaths(EvalState & state) override; @@ -35,9 +36,10 @@ public: static InstallableAttrPath parse( ref state, SourceExprCommand & cmd, - Value * v, + Value & v, std::string_view prefix, - ExtendedOutputsSpec extendedOutputsSpec); + ExtendedOutputsSpec extendedOutputsSpec + ); }; } diff --git a/lix/libcmd/installable-flake.cc b/lix/libcmd/installable-flake.cc index 60150c6f5..700c43688 100644 --- a/lix/libcmd/installable-flake.cc +++ b/lix/libcmd/installable-flake.cc @@ -136,9 +136,9 @@ DerivedPathsWithInfo InstallableFlake::toDerivedPaths(EvalState & state) }}; } -std::pair InstallableFlake::toValue(EvalState & state) +std::pair InstallableFlake::toValue(EvalState & state) { - return {&getCursor(state)->forceValue(state), noPos}; + return {getCursor(state)->forceValue(state), noPos}; } std::vector> diff --git a/lix/libcmd/installable-flake.hh b/lix/libcmd/installable-flake.hh index a608e702a..b3c62dbf6 100644 --- a/lix/libcmd/installable-flake.hh +++ b/lix/libcmd/installable-flake.hh @@ -55,7 +55,7 @@ struct InstallableFlake : InstallableValue DerivedPathsWithInfo toDerivedPaths(EvalState & state) override; - std::pair toValue(EvalState & state) override; + std::pair toValue(EvalState & state) override; /** * Get a cursor to every attrpath in getActualAttrPaths() that diff --git a/lix/libcmd/installable-value.cc b/lix/libcmd/installable-value.cc index d9ef4f7bf..de6ffcc31 100644 --- a/lix/libcmd/installable-value.cc +++ b/lix/libcmd/installable-value.cc @@ -9,8 +9,9 @@ std::vector> InstallableValue::getCursors(EvalState & state) { auto evalCache = - std::make_shared(std::nullopt, - [&](EvalState & state) { return toValue(state).first; }); + std::make_shared(std::nullopt, [&](EvalState & state) { + return toValue(state).first; + }); return {evalCache->getRoot()}; } diff --git a/lix/libcmd/installable-value.hh b/lix/libcmd/installable-value.hh index 23dd66901..04f630650 100644 --- a/lix/libcmd/installable-value.hh +++ b/lix/libcmd/installable-value.hh @@ -77,7 +77,7 @@ struct InstallableValue : Installable virtual ~InstallableValue() { } - virtual std::pair toValue(EvalState & state) = 0; + virtual std::pair toValue(EvalState & state) = 0; /** * Get a cursor to each value this Installable could refer to. diff --git a/lix/libcmd/installables.cc b/lix/libcmd/installables.cc index 3db81e12a..c77ae30e7 100644 --- a/lix/libcmd/installables.cc +++ b/lix/libcmd/installables.cc @@ -235,8 +235,7 @@ void SourceExprCommand::completeInstallable(EvalState & state, AddCompletions & prefix_ = ""; } - auto [v, pos] = findAlongAttrPath(state, prefix_, *autoArgs, root); - Value &v1(*v); + auto [v1, pos] = findAlongAttrPath(state, prefix_, *autoArgs, root); state.forceValue(v1, pos); Value v2; state.autoCallFunction(*autoArgs, v1, v2, pos); @@ -412,15 +411,15 @@ ref openEvalCache( if (getEnv("NIX_ALLOW_EVAL").value_or("1") == "0") throw Error("not everything is cached, but evaluation is not allowed"); - auto vFlake = state.ctx.mem.allocValue(); - flake::callFlake(state, *lockedFlake, *vFlake); + Value vFlake; + flake::callFlake(state, *lockedFlake, vFlake); - state.forceAttrs(*vFlake, noPos, "while parsing cached flake data"); + state.forceAttrs(vFlake, noPos, "while parsing cached flake data"); - auto aOutputs = vFlake->attrs()->get(state.ctx.symbols.create("outputs")); + auto aOutputs = vFlake.attrs()->get(state.ctx.symbols.create("outputs")); assert(aOutputs); - return aOutputs->value; + return *aOutputs->value; }; if (fingerprint) { @@ -465,10 +464,9 @@ Installables SourceExprCommand::parseInstallables( for (auto & s : ss) { auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(s); - result.push_back( - make_ref( - InstallableAttrPath::parse( - evaluator, *this, vFile, std::move(prefix), std::move(extendedOutputsSpec)))); + result.push_back(make_ref(InstallableAttrPath::parse( + evaluator, *this, *vFile, std::move(prefix), std::move(extendedOutputsSpec) + ))); } } else { diff --git a/lix/libcmd/repl.cc b/lix/libcmd/repl.cc index 8f9237c53..21d83cfd0 100644 --- a/lix/libcmd/repl.cc +++ b/lix/libcmd/repl.cc @@ -949,7 +949,7 @@ void NixRepl::loadFiles() for (auto & [i, what] : getValues()) { notice("Loading installable '%1%'...", Magenta(what)); - addAttrsToScope(*i); + addAttrsToScope(i); } loadReplOverlays(); diff --git a/lix/libcmd/repl.hh b/lix/libcmd/repl.hh index 1a04bc5b9..102414b75 100644 --- a/lix/libcmd/repl.hh +++ b/lix/libcmd/repl.hh @@ -8,7 +8,7 @@ namespace nix { struct AbstractNixRepl : NeverAsync { - typedef std::vector> AnnotatedValues; + typedef std::vector> AnnotatedValues; static ReplExitStatus run(const SearchPath & searchPath, diff --git a/lix/libexpr/attr-path.cc b/lix/libexpr/attr-path.cc index 813b5ca57..cde6e7a11 100644 --- a/lix/libexpr/attr-path.cc +++ b/lix/libexpr/attr-path.cc @@ -69,13 +69,12 @@ std::string unparseAttrPath(std::vector const & attrPath) return ret.str(); } - -std::pair findAlongAttrPath(EvalState & state, const std::string & attrPath, - Bindings & autoArgs, Value & vIn) +std::pair +findAlongAttrPath(EvalState & state, const std::string & attrPath, Bindings & autoArgs, Value & vIn) { auto tokens = parseAttrPath(attrPath); - Value * v = &vIn; + Value v = vIn; PosIdx pos = noPos; for (auto [attrPathIdx, attr] : enumerate(tokens)) { @@ -84,10 +83,10 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin auto attrIndex = string2Int(attr); /* Evaluate the expression. */ - Value * vNew = state.ctx.mem.allocValue(); - state.autoCallFunction(autoArgs, *v, *vNew, pos); + Value vNew; + state.autoCallFunction(autoArgs, v, vNew, pos); v = vNew; - state.forceValue(*v, noPos); + state.forceValue(v, noPos); /* It should evaluate to either a set or an expression, according to what is specified in the attrPath. */ @@ -96,7 +95,7 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin if (attr.empty()) throw Error("empty attribute name in selection path '%1%'", attrPath); - if (v->type() != nAttrs) { + if (v.type() != nAttrs) { auto pathPart = std::vector(tokens.begin(), tokens.begin() + attrPathIdx); state.ctx.errors @@ -105,17 +104,18 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin "set but is %3%: %4%", attrPath, unparseAttrPath(pathPart), - showType(*v), - ValuePrinter(state, *v, errorPrintOptions) + showType(v), + ValuePrinter(state, v, errorPrintOptions) ) .debugThrow(); } - auto a = v->attrs()->get(state.ctx.symbols.create(attr)); + auto a = v.attrs()->get(state.ctx.symbols.create(attr)); if (!a) { std::set attrNames; - for (auto & attr : *v->attrs()) + for (auto & attr : *v.attrs()) { attrNames.emplace(state.ctx.symbols[attr.name]); + } auto suggestions = Suggestions::bestMatches(attrNames, attr); auto pathPart = @@ -127,33 +127,33 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin attr, attrPath, unparseAttrPath(pathPart), - ValuePrinter(state, *v, errorPrintOptions) + ValuePrinter(state, v, errorPrintOptions) ); } - v = &*a->value; + v = *a->value; pos = a->pos; } else { - if (!v->isList()) { + if (!v.isList()) { state.ctx.errors .make( "the expression selected by the selection path '%1%' should be a list but " "is %2%: %3%", attrPath, - showType(*v), - ValuePrinter(state, *v, errorPrintOptions) + showType(v), + ValuePrinter(state, v, errorPrintOptions) ) .debugThrow(); } - if (*attrIndex >= v->listSize()) { + if (*attrIndex >= v.listSize()) { throw AttrPathNotFound( "list index %1% in selection path '%2%' is out of range for list %3%", *attrIndex, attrPath, - ValuePrinter(state, *v, errorPrintOptions) + ValuePrinter(state, v, errorPrintOptions) ); } - v = v->listElems()[*attrIndex]; + v = *v.listElems()[*attrIndex]; pos = noPos; } @@ -165,7 +165,7 @@ std::pair findAlongAttrPath(EvalState & state, const std::strin std::pair findPackageFilename(EvalState & state, Value & v, std::string what) { - Value * v2; + Value v2; try { auto dummyArgs = state.ctx.mem.allocBindings(0); v2 = findAlongAttrPath(state, "meta.position", *dummyArgs, v).first; @@ -176,7 +176,9 @@ std::pair findPackageFilename(EvalState & state, Value & v // FIXME: is it possible to extract the Pos object instead of doing this // toString + parsing? NixStringContext context; - auto path = state.coerceToPath(noPos, *v2, context, "while evaluating the 'meta.position' attribute of a derivation"); + auto path = state.coerceToPath( + noPos, v2, context, "while evaluating the 'meta.position' attribute of a derivation" + ); auto fn = path.canonical().abs(); diff --git a/lix/libexpr/attr-path.hh b/lix/libexpr/attr-path.hh index ba11411f1..78667a7e1 100644 --- a/lix/libexpr/attr-path.hh +++ b/lix/libexpr/attr-path.hh @@ -10,11 +10,9 @@ namespace nix { MakeError(AttrPathNotFound, Error); MakeError(NoPositionInfo, Error); -std::pair findAlongAttrPath( - EvalState & state, - const std::string & attrPath, - Bindings & autoArgs, - Value & vIn); +std::pair findAlongAttrPath( + EvalState & state, const std::string & attrPath, Bindings & autoArgs, Value & vIn +); /** * Heuristic to find the filename and lineno or a nix value. diff --git a/lix/libexpr/eval-cache.cc b/lix/libexpr/eval-cache.cc index 2da23d303..d67c76b25 100644 --- a/lix/libexpr/eval-cache.cc +++ b/lix/libexpr/eval-cache.cc @@ -341,7 +341,7 @@ EvalCache::EvalCache( { } -Value * EvalCache::getRootValue(EvalState & state) +Value & EvalCache::getRootValue(EvalState & state) { if (!value) { debug("getting root value"); @@ -362,8 +362,9 @@ AttrCursor::AttrCursor( std::optional> && cachedValue) : root(root), parent(parent), cachedValue(std::move(cachedValue)) { - if (value) - _value = allocRootValue(value); + if (value) { + _value = allocRootValue(*value); + } } AttrKey AttrCursor::getKey() @@ -386,11 +387,11 @@ Value & AttrCursor::getValue(EvalState & state) auto attr = vParent.attrs()->get(state.ctx.symbols.create(parent->second)); if (!attr) throw Error("attribute '%s' is unexpectedly missing", getAttrPathStr(state)); - _value = allocRootValue(attr->value); + _value = allocRootValue(*attr->value); } else _value = allocRootValue(root->getRootValue(state)); } - return **_value; + return *_value; } std::vector AttrCursor::getAttrPath(EvalState & state) const diff --git a/lix/libexpr/eval-cache.hh b/lix/libexpr/eval-cache.hh index 5cd78f027..bd8541b49 100644 --- a/lix/libexpr/eval-cache.hh +++ b/lix/libexpr/eval-cache.hh @@ -12,7 +12,7 @@ namespace nix::eval_cache { struct AttrDb; class AttrCursor; -typedef std::function RootLoader; +typedef std::function RootLoader; /** * EvalState with caching support. Historically this was part of EvalState, @@ -42,7 +42,7 @@ class EvalCache : public std::enable_shared_from_this RootLoader rootLoader; RootValue value; - Value * getRootValue(EvalState & state); + Value & getRootValue(EvalState & state); public: diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc index bbcb4eb22..d2f96ee6e 100644 --- a/lix/libexpr/eval.cc +++ b/lix/libexpr/eval.cc @@ -69,9 +69,9 @@ gdb.execute("handle SIGPWR SIGXCPU ignore") namespace nix { -RootValue allocRootValue(Value * v) +RootValue allocRootValue(Value v) { - return std::allocate_shared(TraceableAllocator(), v); + return std::allocate_shared(TraceableAllocator(), v); } // Pretty print types for assertion errors @@ -1157,12 +1157,12 @@ void ExprSet::eval(EvalState & state, Env & env, Value & v) been substituted into the bodies of the other attributes. Hence we need __overrides.) */ if (hasOverrides) { - Value * vOverrides = (*v.attrs())[overrides->second.displ].value; - state.forceAttrs(*vOverrides, noPos, "while evaluating the `__overrides` attribute"); - Bindings * newBnds = state.ctx.mem.allocBindings(capacity + vOverrides->attrs()->size()); + Value & vOverrides = *(*v.attrs())[overrides->second.displ].value; + state.forceAttrs(vOverrides, noPos, "while evaluating the `__overrides` attribute"); + Bindings * newBnds = state.ctx.mem.allocBindings(capacity + vOverrides.attrs()->size()); for (auto & i : *v.attrs()) newBnds->push_back(i); - for (auto & i : *vOverrides->attrs()) { + for (auto & i : *vOverrides.attrs()) { ExprAttrs::AttrDefs::iterator j = attrs.find(i.name); if (j != attrs.end()) { (*newBnds)[j->second.displ] = i; @@ -1507,15 +1507,19 @@ FormalsMatch matchupLambdaAttrs(EvalState & state, Env & env, Displacement & dis return result; } -Env & SimplePattern::match(ExprLambda & lambda, EvalState & state, Env & up, Value * arg, const PosIdx pos) +Env & SimplePattern::match( + ExprLambda & lambda, EvalState & state, Env & up, Value & arg, const PosIdx pos +) { Env & env2(state.ctx.mem.allocEnv(1)); env2.up = &up; - env2.values[0] = arg; + env2.values[0] = &arg; return env2; } -Env & AttrsPattern::match(ExprLambda & lambda, EvalState & state, Env & up, Value * arg, const PosIdx pos) +Env & AttrsPattern::match( + ExprLambda & lambda, EvalState & state, Env & up, Value & arg, const PosIdx pos +) { auto & ctx = state.ctx; @@ -1524,27 +1528,23 @@ Env & AttrsPattern::match(ExprLambda & lambda, EvalState & state, Env & up, Valu Displacement displ = 0; try { - state.forceAttrs(*arg, lambda.pos, "while evaluating the value passed for the lambda argument"); + state.forceAttrs( + arg, lambda.pos, "while evaluating the value passed for the lambda argument" + ); } catch (Error & e) { if (pos) e.addTrace(ctx.positions[pos], "from call site"); throw; } - if (name) - env2.values[displ++] = arg; + if (name) { + env2.values[displ++] = &arg; + } ///* For each formal argument, get the actual argument. If // there is no matching actual argument but the formal // argument has a default, use the default. */ - auto const formalsMatch = matchupLambdaAttrs( - state, - env2, - displ, - *this, - *arg->attrs(), - ctx.symbols - ); - + auto const formalsMatch = + matchupLambdaAttrs(state, env2, displ, *this, *arg.attrs(), ctx.symbols); if (!formalsMatch.unexpected.empty() || !formalsMatch.missing.empty()) { Suggestions sug; // empty suggestions -> no suggestions @@ -1616,7 +1616,7 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, ExprLambda & lambda(*vCur.lambda().fun); - Env & env2 = lambda.pattern->match(lambda, *this, *vCur.lambda().env(), args[0], pos); + Env & env2 = lambda.pattern->match(lambda, *this, *vCur.lambda().env(), *args[0], pos); ctx.stats.nrFunctionCalls++; if (ctx.stats.countCalls) ctx.stats.addCall(lambda); @@ -1781,10 +1781,10 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res, PosI if (fun.type() == nAttrs) { auto found = fun.attrs()->get(ctx.s.functor); if (found) { - Value * v = ctx.mem.allocValue(); - callFunction(*found->value, fun, *v, pos); - forceValue(*v, pos); - return autoCallFunction(args, *v, res, pos); + Value v; + callFunction(*found->value, fun, v, pos); + forceValue(v, pos); + return autoCallFunction(args, v, res, pos); } } @@ -1829,7 +1829,8 @@ https://docs.lix.systems/manual/lix/stable/language/constructs.html#functions)", } } - callFunction(fun, ctx.mem.allocValue()->mkAttrs(attrs), res, pos); + Value vAttrs{NewValueAs::attrs, attrs.finish()}; + callFunction(fun, vAttrs, res, pos); } diff --git a/lix/libexpr/flake/flake.cc b/lix/libexpr/flake/flake.cc index f86b41997..3f343de3c 100644 --- a/lix/libexpr/flake/flake.cc +++ b/lix/libexpr/flake/flake.cc @@ -96,7 +96,7 @@ static void expectType(EvalState & state, ValueType type, static std::pair, std::optional> parseFlakeInputs( EvalState & state, - Value * value, + Value & value, const PosIdx pos, const std::optional & baseDir, InputPath lockRootPath, @@ -144,11 +144,17 @@ static void parseFlakeInputAttr(EvalState & state, const Attr & attr, fetchers:: #pragma GCC diagnostic pop } -static FlakeInput parseFlakeInput(EvalState & state, - const std::string & inputName, Value * value, const PosIdx pos, - const std::optional & baseDir, InputPath lockRootPath, unsigned depth) +static FlakeInput parseFlakeInput( + EvalState & state, + const std::string & inputName, + Value & value, + const PosIdx pos, + const std::optional & baseDir, + InputPath lockRootPath, + unsigned depth +) { - expectType(state, nAttrs, *value, pos); + expectType(state, nAttrs, value, pos); FlakeInput input; @@ -160,7 +166,7 @@ static FlakeInput parseFlakeInput(EvalState & state, fetchers::Attrs attrs; std::optional url; - for (nix::Attr attr : *(value->attrs())) { + for (nix::Attr attr : *(value.attrs())) { try { if (attr.name == sUrl) { expectType(state, nString, *attr.value, attr.pos); @@ -172,7 +178,7 @@ static FlakeInput parseFlakeInput(EvalState & state, } else if (attr.name == sInputs) { input.overrides = parseFlakeInputs( - state, attr.value, attr.pos, baseDir, lockRootPath, depth + 1, false + state, *attr.value, attr.pos, baseDir, lockRootPath, depth + 1, false ) .first; } else if (attr.name == sFollows) { @@ -218,7 +224,7 @@ static FlakeInput parseFlakeInput(EvalState & state, static std::pair, std::optional> parseFlakeInputs( EvalState & state, - Value * value, + Value & value, const PosIdx pos, const std::optional & baseDir, InputPath lockRootPath, @@ -228,10 +234,10 @@ static std::pair, std::optional> { std::map inputs; - expectType(state, nAttrs, *value, pos); + expectType(state, nAttrs, value, pos); std::optional selfAttrs = std::nullopt; - for (const nix::Attr & inputAttr : *(*value).attrs()) { + for (const nix::Attr & inputAttr : *value.attrs()) { std::string inputName{state.ctx.symbols[inputAttr.name]}; if (inputName == "self") { experimentalFeatureSettings.require(Xp::FlakeSelfAttrs); @@ -251,7 +257,7 @@ static std::pair, std::optional> inputs.emplace( inputName, parseFlakeInput( - state, inputName, inputAttr.value, inputAttr.pos, baseDir, lockRootPath, depth + state, inputName, *inputAttr.value, inputAttr.pos, baseDir, lockRootPath, depth ) ); } @@ -337,7 +343,7 @@ static Flake getFlake( if (auto inputs = vInfo.attrs()->get(sInputs)) { auto [flakeInputs, selfAttrs] = - parseFlakeInputs(state, inputs->value, inputs->pos, flakeDir, lockRootPath, 0, true); + parseFlakeInputs(state, *inputs->value, inputs->pos, flakeDir, lockRootPath, 0, true); flake.inputs = std::move(flakeInputs); flake.selfAttrs = std::move(selfAttrs); } @@ -926,13 +932,17 @@ void callFlake(EvalState & state, vRootSubdir->mkString(lockedFlake.flake.lockedRef.subdir); if (!state.ctx.caches.vCallFlake) { - state.ctx.caches.vCallFlake = allocRootValue(state.ctx.mem.allocValue()); - state.eval(state.ctx.parseExprFromString( - #include "call-flake.nix.gen.hh" - , CanonPath::root), **state.ctx.caches.vCallFlake); + state.ctx.caches.vCallFlake = allocRootValue({}); + state.eval( + state.ctx.parseExprFromString( +#include "call-flake.nix.gen.hh" + , CanonPath::root + ), + *state.ctx.caches.vCallFlake + ); } - state.callFunction(**state.ctx.caches.vCallFlake, *vLocks, *vTmp1, noPos); + state.callFunction(*state.ctx.caches.vCallFlake, *vLocks, *vTmp1, noPos); state.callFunction(*vTmp1, *vRootSrc, *vTmp2, noPos); state.callFunction(*vTmp2, *vRootSubdir, vRes, noPos); } diff --git a/lix/libexpr/get-drvs.cc b/lix/libexpr/get-drvs.cc index 7cdb0d2f8..5599611bf 100644 --- a/lix/libexpr/get-drvs.cc +++ b/lix/libexpr/get-drvs.cc @@ -384,8 +384,7 @@ bool DrvInfo::queryMetaBool(EvalState & state, const std::string & name, bool de return def; } - -void DrvInfo::setMeta(EvalState & state, const std::string & name, Value * v) +void DrvInfo::setMeta(EvalState & state, const std::string & name, Value & v) { getMeta(state); auto attrs = state.ctx.buildBindings(1 + (meta ? meta->size() : 0)); @@ -394,7 +393,7 @@ void DrvInfo::setMeta(EvalState & state, const std::string & name, Value * v) for (auto i : *meta) if (i.name != sym) attrs.insert(i); - if (v) attrs.insert(sym, v); + attrs.insert(sym, &v); meta = attrs.finish(); } diff --git a/lix/libexpr/get-drvs.hh b/lix/libexpr/get-drvs.hh index 679534cc5..f3e4f3009 100644 --- a/lix/libexpr/get-drvs.hh +++ b/lix/libexpr/get-drvs.hh @@ -73,7 +73,7 @@ public: std::string queryMetaString(EvalState & state, const std::string & name); NixInt queryMetaInt(EvalState & state, const std::string & name, NixInt def); bool queryMetaBool(EvalState & state, const std::string & name, bool def); - void setMeta(EvalState & state, const std::string & name, Value * v); + void setMeta(EvalState & state, const std::string & name, Value & v); /* MetaInfo queryMetaInfo(EvalState & state) const; diff --git a/lix/libexpr/json-to-value.cc b/lix/libexpr/json-to-value.cc index be8424f3e..f184c2f7b 100644 --- a/lix/libexpr/json-to-value.cc +++ b/lix/libexpr/json-to-value.cc @@ -8,11 +8,6 @@ namespace nix { -/* - * Used for `JSONObjectState` - */ -using ValueMap = GcMap; - // for more information, refer to // https://github.com/nlohmann/json/blob/master/include/nlohmann/detail/input/json_sax.hpp class JSONSax : nlohmann::json_sax { @@ -26,49 +21,57 @@ class JSONSax : nlohmann::json_sax { assert(false && "tried to close toplevel json parser state"); } explicit JSONState(std::unique_ptr && p) : parent(std::move(p)) {} - explicit JSONState(Value * v) : v(allocRootValue(v)) {} + JSONState() = default; JSONState(JSONState & p) = delete; Value & value(EvalState & state) { - if (!v) - v = allocRootValue(state.ctx.mem.allocValue()); - return **v; + if (!v) { + v = allocRootValue({}); + } + return *v; } virtual ~JSONState() {} - virtual void add() {} + virtual void add(EvalState & state) {} }; class JSONObjectState : public JSONState { using JSONState::JSONState; - ValueMap attrs; + GcMap attrs; + Symbol _key; std::unique_ptr resolve(EvalState & state) override { auto attrs2 = state.ctx.buildBindings(attrs.size()); - for (auto & i : attrs) - attrs2.insert(i.first, i.second); + for (auto & i : attrs) { + auto v = state.ctx.mem.allocValue(); + *v = i.second; + attrs2.insert(i.first, v); + } parent->value(state).mkAttrs(attrs2.alreadySorted()); return std::move(parent); } - void add() override { v = nullptr; } + void add(EvalState & state) override { + attrs.insert_or_assign(_key, value(state)); + v = nullptr; + } public: void key(string_t & name, EvalState & state) { - attrs.insert_or_assign(state.ctx.symbols.create(name), &value(state)); + _key = state.ctx.symbols.create(name); } }; class JSONListState : public JSONState { - GcVector values; + GcVector values; std::unique_ptr resolve(EvalState & state) override { auto list = state.ctx.mem.newList(values.size()); parent->value(state) = {NewValueAs::list, list}; for (size_t n = 0; n < values.size(); ++n) { - list->elems[n] = values[n]; + *(list->elems[n] = state.ctx.mem.allocValue()) = values[n]; } return std::move(parent); } - void add() override { + void add(EvalState & state) override { values.push_back(*v); v = nullptr; } @@ -83,26 +86,31 @@ class JSONSax : nlohmann::json_sax { std::unique_ptr rs; public: - JSONSax(EvalState & state, Value & v) : state(state), rs(new JSONState(&v)) {}; + JSONSax(EvalState & state) : state(state), rs(new JSONState()) {}; + + Value result() + { + return rs->value(state); + } bool null() override { rs->value(state).mkNull(); - rs->add(); + rs->add(state); return true; } bool boolean(bool val) override { rs->value(state).mkBool(val); - rs->add(); + rs->add(state); return true; } bool number_integer(number_integer_t val) override { rs->value(state).mkInt(val); - rs->add(); + rs->add(state); return true; } @@ -115,21 +123,21 @@ public: } NixInt::Inner val = val_; rs->value(state).mkInt(val); - rs->add(); + rs->add(state); return true; } bool number_float(number_float_t val, const string_t & s) override { rs->value(state).mkFloat(val); - rs->add(); + rs->add(state); return true; } bool string(string_t & val) override { rs->value(state).mkString(val); - rs->add(); + rs->add(state); return true; } @@ -156,7 +164,7 @@ public: bool end_object() override { rs = rs->resolve(state); - rs->add(); + rs->add(state); return true; } @@ -179,10 +187,11 @@ public: void parseJSON(EvalState & state, const std::string_view & s_, Value & v) { - JSONSax parser(state, v); + JSONSax parser(state); bool res = JSON::sax_parse(s_, &parser); if (!res) throw JSONParseError("Invalid JSON Value"); + v = parser.result(); } } diff --git a/lix/libexpr/nixexpr.hh b/lix/libexpr/nixexpr.hh index bb40fa566..d1b0c6509 100644 --- a/lix/libexpr/nixexpr.hh +++ b/lix/libexpr/nixexpr.hh @@ -409,7 +409,8 @@ struct Pattern { virtual std::shared_ptr buildEnv(const StaticEnv * up) = 0; virtual void accept(ExprVisitor & ev) = 0; - virtual Env & match(ExprLambda & lambda, EvalState & state, Env & up, Value * arg, const PosIdx pos) = 0; + virtual Env & + match(ExprLambda & lambda, EvalState & state, Env & up, Value & arg, const PosIdx pos) = 0; virtual void addBindingsToJSON(JSON & out, const SymbolTable & symbols) const = 0; }; @@ -424,7 +425,8 @@ struct SimplePattern : Pattern virtual std::shared_ptr buildEnv(const StaticEnv * up) override; virtual void accept(ExprVisitor & ev) override; - virtual Env & match(ExprLambda & lambda, EvalState & state, Env & up, Value * arg, const PosIdx pos) override; + virtual Env & + match(ExprLambda & lambda, EvalState & state, Env & up, Value & arg, const PosIdx pos) override; virtual void addBindingsToJSON(JSON & out, const SymbolTable & symbols) const override; }; @@ -445,7 +447,8 @@ struct AttrsPattern : Pattern virtual std::shared_ptr buildEnv(const StaticEnv * up) override; virtual void accept(ExprVisitor & ev) override; - virtual Env & match(ExprLambda & lambda, EvalState & state, Env & up, Value * arg, const PosIdx pos) override; + virtual Env & + match(ExprLambda & lambda, EvalState & state, Env & up, Value & arg, const PosIdx pos) override; virtual void addBindingsToJSON(JSON & out, const SymbolTable & symbols) const override; diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index b2d722290..2318eb23c 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -196,18 +196,22 @@ static void import(EvalState & state, Value & vPath, Value * vScope, Value & v) w->mkAttrs(attrs); if (!state.ctx.caches.vImportedDrvToDerivation) { - state.ctx.caches.vImportedDrvToDerivation = allocRootValue(state.ctx.mem.allocValue()); - state.eval(state.ctx.parseExprFromString( - #include "imported-drv-to-derivation.nix.gen.hh" - , CanonPath::root), **state.ctx.caches.vImportedDrvToDerivation); + state.ctx.caches.vImportedDrvToDerivation = allocRootValue({}); + state.eval( + state.ctx.parseExprFromString( +#include "imported-drv-to-derivation.nix.gen.hh" + , CanonPath::root + ), + *state.ctx.caches.vImportedDrvToDerivation + ); } state.forceFunction( - **state.ctx.caches.vImportedDrvToDerivation, + *state.ctx.caches.vImportedDrvToDerivation, noPos, "while evaluating imported-drv-to-derivation.nix.gen.hh" ); - v = {NewValueAs::app, state.ctx.mem, **state.ctx.caches.vImportedDrvToDerivation, *w}; + v = {NewValueAs::app, state.ctx.mem, *state.ctx.caches.vImportedDrvToDerivation, *w}; state.forceAttrs(v, noPos, "while calling imported-drv-to-derivation.nix.gen.hh"); } @@ -425,49 +429,70 @@ struct CompareValues : NeverAsync CompareValues(EvalState & state, const std::string_view && errorCtx) : state(state), errorCtx(errorCtx) { }; - bool operator () (Value * v1, Value * v2) const + bool operator()(Value * v1, Value * v2) const + { + return (*this)(*v1, *v2, errorCtx); + } + + bool operator()(Value & v1, Value & v2) const { return (*this)(v1, v2, errorCtx); } - bool operator () (Value * v1, Value * v2, std::string_view errorCtx) const + bool operator()(Value & v1, Value & v2, std::string_view errorCtx) const { try { - if (v1->type() == nFloat && v2->type() == nInt) { - return v1->fpoint() < v2->integer().value; + if (v1.type() == nFloat && v2.type() == nInt) { + return v1.fpoint() < v2.integer().value; } - if (v1->type() == nInt && v2->type() == nFloat) { - return v1->integer().value < v2->fpoint(); + if (v1.type() == nInt && v2.type() == nFloat) { + return v1.integer().value < v2.fpoint(); + } + if (v1.type() != v2.type()) { + state.ctx.errors + .make("cannot compare %s with %s", showType(v1), showType(v2)) + .debugThrow(); } - if (v1->type() != v2->type()) - state.ctx.errors.make("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" - switch (v1->type()) { - case nInt: - return v1->integer() < v2->integer(); - case nFloat: - return v1->fpoint() < v2->fpoint(); - case nString: - return v1->str() < v2->str(); - case nPath: - return strcmp(v1->string().content, v2->string().content) < 0; - case nList: - // Lexicographic comparison - for (size_t i = 0;; i++) { - if (i == v2->listSize()) { - return false; - } else if (i == v1->listSize()) { - return true; - } else if (!state.eqValues(*v1->listElems()[i], *v2->listElems()[i], noPos, errorCtx)) { - return (*this)(v1->listElems()[i], v2->listElems()[i], "while comparing two list elements"); - } + switch (v1.type()) { + case nInt: + return v1.integer() < v2.integer(); + case nFloat: + return v1.fpoint() < v2.fpoint(); + case nString: + return v1.str() < v2.str(); + case nPath: + return strcmp(v1.string().content, v2.string().content) < 0; + case nList: + // Lexicographic comparison + for (size_t i = 0;; i++) { + if (i == v2.listSize()) { + return false; + } else if (i == v1.listSize()) { + return true; + } else if (!state.eqValues( + *v1.listElems()[i], *v2.listElems()[i], noPos, errorCtx + )) + { + return (*this)( + *v1.listElems()[i], + *v2.listElems()[i], + "while comparing two list elements" + ); } + } default: - state.ctx.errors.make("cannot compare %s with %s; values of that type are incomparable", showType(*v1), showType(*v2)).debugThrow(); - #pragma GCC diagnostic pop - } + state.ctx.errors + .make( + "cannot compare %s with %s; values of that type are incomparable", + showType(v1), + showType(v2) + ) + .debugThrow(); +#pragma GCC diagnostic pop + } } catch (Error & e) { if (!errorCtx.empty()) e.addTrace(nullptr, errorCtx); @@ -2255,7 +2280,7 @@ static void prim_sort(EvalState & state, Value * * args, Value & v) if (args[0]->isPrimOp()) { auto ptr = args[0]->primOp()->fun.target(); if (ptr && *ptr == prim_lessThan) - return CompareValues(state, "while evaluating the ordering function passed to builtins.sort")(a, b); + return CompareValues(state, "while evaluating the ordering function passed to builtins.sort")(*a, *b); } Value * vs[] = {a, b}; @@ -2493,7 +2518,7 @@ static void prim_lessThan(EvalState & state, Value * * args, Value & v) state.forceValue(*args[0], noPos); state.forceValue(*args[1], noPos); CompareValues comp(state, ""); - v.mkBool(comp(args[0], args[1])); + v.mkBool(comp(*args[0], *args[1])); } diff --git a/lix/libexpr/value.hh b/lix/libexpr/value.hh index 44f923745..e01e9b70f 100644 --- a/lix/libexpr/value.hh +++ b/lix/libexpr/value.hh @@ -1066,8 +1066,7 @@ using PrimOp = Value::PrimOp; /** * A value allocated in traceable memory. */ -typedef std::shared_ptr RootValue; - -RootValue allocRootValue(Value * v); +typedef std::shared_ptr RootValue; +RootValue allocRootValue(Value v); } diff --git a/lix/nix/bundle.cc b/lix/nix/bundle.cc index 0bad9866c..03a2dbcfb 100644 --- a/lix/nix/bundle.cc +++ b/lix/nix/bundle.cc @@ -96,20 +96,22 @@ struct CmdBundle : InstallableCommand lockFlags }; - auto vRes = evaluator->mem.allocValue(); - evalState->callFunction(*bundler.toValue(*evalState).first, *val, *vRes, noPos); + Value vRes; + auto fn = bundler.toValue(*evalState).first; + evalState->callFunction(fn, val, vRes, noPos); - if (!evalState->isDerivation(*vRes)) + if (!evalState->isDerivation(vRes)) { throw Error("the bundler '%s' does not produce a derivation", bundler.what()); + } - auto attr1 = vRes->attrs()->get(evaluator->s.drvPath); + auto attr1 = vRes.attrs()->get(evaluator->s.drvPath); if (!attr1) throw Error("the bundler '%s' does not produce a derivation", bundler.what()); NixStringContext context2; auto drvPath = evalState->coerceToStorePath(attr1->pos, *attr1->value, context2, ""); - auto attr2 = vRes->attrs()->get(evaluator->s.outPath); + auto attr2 = vRes.attrs()->get(evaluator->s.outPath); if (!attr2) throw Error("the bundler '%s' does not produce a derivation", bundler.what()); @@ -123,7 +125,7 @@ struct CmdBundle : InstallableCommand })); if (!outLink) { - auto * attr = vRes->attrs()->get(evaluator->s.name); + auto * attr = vRes.attrs()->get(evaluator->s.name); if (!attr) throw Error("attribute 'name' missing"); outLink = evalState->forceStringNoCtx(*attr->value, attr->pos, ""); diff --git a/lix/nix/edit.cc b/lix/nix/edit.cc index ace8d0029..cab9b6e38 100644 --- a/lix/nix/edit.cc +++ b/lix/nix/edit.cc @@ -37,7 +37,7 @@ struct CmdEdit : InstallableCommand auto [v, pos] = installableValue->toValue(*state); try { - return findPackageFilename(*state, *v, installable->what()); + return findPackageFilename(*state, v, installable->what()); } catch (NoPositionInfo &) { throw Error("cannot find position information for '%s", installableValue->what()); } diff --git a/lix/nix/eval.cc b/lix/nix/eval.cc index 2adc4bf51..64beb152e 100644 --- a/lix/nix/eval.cc +++ b/lix/nix/eval.cc @@ -79,21 +79,26 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption NixStringContext context; if (apply) { - auto vApply = evaluator->mem.allocValue(); - state->eval(evaluator->parseExprFromString(*apply, CanonPath::fromCwd()), *vApply); - auto vRes = evaluator->mem.allocValue(); - state->callFunction(*vApply, *v, *vRes, noPos); + Value vApply; + state->eval(evaluator->parseExprFromString(*apply, CanonPath::fromCwd()), vApply); + Value vRes; + state->callFunction(vApply, v, vRes, noPos); v = vRes; } if (raw) { logger->pause(); - writeFull(STDOUT_FILENO, *state->coerceToString(noPos, *v, context, "while generating the eval command output")); + writeFull( + STDOUT_FILENO, + *state->coerceToString( + noPos, v, context, "while generating the eval command output" + ) + ); } else if (json) { - logger->cout("%s", printValueAsJSON(*state, true, *v, pos, context, false)); + logger->cout("%s", printValueAsJSON(*state, true, v, pos, context, false)); } else @@ -102,8 +107,8 @@ struct CmdEval : MixJSON, InstallableCommand, MixReadOnlyOption "%s", ValuePrinter( *state, - *v, - PrintOptions { + v, + PrintOptions{ .force = true, .derivationPaths = true, .errors = ErrorPrintBehavior::ThrowTopLevel, diff --git a/lix/nix/flake.cc b/lix/nix/flake.cc index a8a857f31..b169cadaf 100644 --- a/lix/nix/flake.cc +++ b/lix/nix/flake.cc @@ -522,9 +522,10 @@ struct CmdFlakeCheck : FlakeCommand fmt("checking NixOS configuration '%s'", attrPath)); Bindings & bindings(*evaluator->mem.allocBindings(0)); auto vToplevel = findAlongAttrPath(*state, "config.system.build.toplevel", bindings, v).first; - state->forceValue(*vToplevel, pos); - if (!state->isDerivation(*vToplevel)) + state->forceValue(vToplevel, pos); + if (!state->isDerivation(vToplevel)) { throw Error("attribute 'config.system.build.toplevel' is not a derivation"); + } } catch (Error & e) { e.addTrace(resolve(pos), HintFmt("while checking the NixOS configuration '%s'", attrPath)); reportError(e); @@ -584,12 +585,12 @@ struct CmdFlakeCheck : FlakeCommand { Activity act(*logger, lvlInfo, actUnknown, "evaluating flake"); - auto vFlake = evaluator->mem.allocValue(); - flake::callFlake(*state, flake, *vFlake); + Value vFlake; + flake::callFlake(*state, flake, vFlake); enumerateOutputs( *state, - *vFlake, + vFlake, [&](const std::string_view name, Value & vOutput, const PosIdx pos) { Activity act(*logger, lvlInfo, actUnknown, fmt("checking flake output '%s'", name)); diff --git a/lix/nix/main.cc b/lix/nix/main.cc index 2294fc294..ad95972c1 100644 --- a/lix/nix/main.cc +++ b/lix/nix/main.cc @@ -357,19 +357,23 @@ static void showHelp(AsyncIoRoot & aio, std::vector subcommand, Nix Evaluator evaluator(aio, {}, aio.blockOn(openStore("dummy://"))); auto state = evaluator.begin(aio); - auto vGenerateManpage = evaluator.mem.allocValue(); - state->eval(evaluator.parseExprFromString( - #include "generate-manpage.nix.gen.hh" - , CanonPath::root), *vGenerateManpage); + Value vGenerateManpage; + state->eval( + evaluator.parseExprFromString( +#include "generate-manpage.nix.gen.hh" + , CanonPath::root + ), + vGenerateManpage + ); - auto vDump = evaluator.mem.allocValue(); - vDump->mkString(toplevel.dumpCli()); + Value vDump; + vDump.mkString(toplevel.dumpCli()); - auto vRes = evaluator.mem.allocValue(); - state->callFunction(*vGenerateManpage, evaluator.builtins.get("false"), *vRes, noPos); - state->callFunction(*vRes, *vDump, *vRes, noPos); + Value vRes; + state->callFunction(vGenerateManpage, evaluator.builtins.get("false"), vRes, noPos); + state->callFunction(vRes, vDump, vRes, noPos); - auto attr = vRes->attrs()->get(evaluator.symbols.create(mdName + ".md")); + auto attr = vRes.attrs()->get(evaluator.symbols.create(mdName + ".md")); if (!attr) throw UsageError("`nix` has no subcommand '%s'", concatStringsSep("", subcommand)); diff --git a/lix/nix/prefetch.cc b/lix/nix/prefetch.cc index 071c77f90..54e3bd692 100644 --- a/lix/nix/prefetch.cc +++ b/lix/nix/prefetch.cc @@ -207,7 +207,7 @@ static int main_nix_prefetch_url(AsyncIoRoot & aio, std::string programName, Str evaluator->paths.resolveExprPath( aio.blockOn(lookupFileArg(*evaluator, args.empty() ? "." : args[0])).unwrap()), vRoot); - Value & v(*findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first); + Value v(findAlongAttrPath(*state, attrPath, autoArgs, vRoot).first); state->forceAttrs(v, noPos, "while evaluating the source attribute to prefetch"); /* Extract the URL. */ diff --git a/lix/nix/repl.cc b/lix/nix/repl.cc index 8895ab78c..d6e184721 100644 --- a/lix/nix/repl.cc +++ b/lix/nix/repl.cc @@ -66,15 +66,15 @@ struct CmdRepl : RawInstallablesCommand if (file){ auto [val, pos] = installable.toValue(*state); auto what = installable.what(); - state->forceValue(*val, pos); + state->forceValue(val, pos); auto autoArgs = getAutoArgs(*evaluator); auto valPost = evaluator->mem.allocValue(); - state->autoCallFunction(*autoArgs, *val, *valPost, pos); + state->autoCallFunction(*autoArgs, val, *valPost, pos); state->forceValue(*valPost, pos); - values.push_back( {valPost, what }); + values.push_back({*valPost, what}); } else { auto [val, pos] = installable.toValue(*state); - values.push_back( {val, what} ); + values.push_back({val, what}); } } return values; diff --git a/lix/nix/upgrade-nix.cc b/lix/nix/upgrade-nix.cc index 723bc9578..2e96efe26 100644 --- a/lix/nix/upgrade-nix.cc +++ b/lix/nix/upgrade-nix.cc @@ -292,12 +292,14 @@ struct CmdUpgradeNix : MixDryRun, EvalCommand auto evaluator = std::make_unique(aio(), SearchPath{}, store); auto state = evaluator->begin(aio()); - auto v = evaluator->mem.allocValue(); - state->eval(evaluator->parseExprFromString(data, CanonPath("/no-such-path")), *v); + Value v; + state->eval(evaluator->parseExprFromString(data, CanonPath("/no-such-path")), v); Bindings & bindings(*evaluator->mem.allocBindings(0)); - auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, *v).first; + auto v2 = findAlongAttrPath(*state, settings.thisSystem, bindings, v).first; - return store->parseStorePath(state->forceString(*v2, noPos, "while evaluating the path tho latest nix version")); + return store->parseStorePath( + state->forceString(v2, noPos, "while evaluating the path tho latest nix version") + ); } }; diff --git a/subprojects/nix-eval-jobs/src/worker.cc b/subprojects/nix-eval-jobs/src/worker.cc index ac8286d1e..ba551fcab 100644 --- a/subprojects/nix-eval-jobs/src/worker.cc +++ b/subprojects/nix-eval-jobs/src/worker.cc @@ -126,7 +126,7 @@ void worker(nix::ref evaluator, nix::Bindings &autoArgs, nix::AutoCloseFD &to, nix::AutoCloseFD &from, MyArgs &args, nix::AsyncIoRoot &aio) { - nix::Value *vRoot = [&]() { + nix::Value vRoot = [&]() { auto state = evaluator->begin(aio); if (args.flake) { auto [flakeRef, fragment, outputSpec] = @@ -138,7 +138,7 @@ void worker(nix::ref evaluator, return flake.toValue(*state).first; } else { - return releaseExprTopLevelValue(*state, autoArgs, args); + return *releaseExprTopLevelValue(*state, autoArgs, args); } }(); @@ -168,11 +168,11 @@ void worker(nix::ref evaluator, nix::JSON{{"attr", attrPathS}, {"attrPath", path}}; try { auto vTmp = - nix::findAlongAttrPath(*state, attrPathS, autoArgs, *vRoot) + nix::findAlongAttrPath(*state, attrPathS, autoArgs, vRoot) .first; auto v = evaluator->mem.allocValue(); - state->autoCallFunction(autoArgs, *vTmp, *v, {}); + state->autoCallFunction(autoArgs, vTmp, *v, {}); if (v->type() == nix::nAttrs) { if (auto drvInfo = nix::getDerivation(*state, *v, false)) { diff --git a/tests/unit/libexpr/attr-path.cc b/tests/unit/libexpr/attr-path.cc index cb08480bd..1c0d3f8fe 100644 --- a/tests/unit/libexpr/attr-path.cc +++ b/tests/unit/libexpr/attr-path.cc @@ -15,7 +15,7 @@ namespace nix { class AttrPathEval : public LibExprTest { public: - std::pair testFindAlongAttrPath(std::string expr, std::string path); + std::pair testFindAlongAttrPath(std::string expr, std::string path); }; RC_GTEST_PROP(AttrPath, prop_round_trip, ()) @@ -29,7 +29,7 @@ RC_GTEST_PROP(AttrPath, prop_round_trip, ()) RC_ASSERT(strings == unparsedReparsed); } -std::pair AttrPathEval::testFindAlongAttrPath(std::string expr, std::string path) +std::pair AttrPathEval::testFindAlongAttrPath(std::string expr, std::string path) { auto v = eval(expr); auto bindings = evalState().ctx.buildBindings(0).finish(); diff --git a/tests/unit/libexpr/derived-path.cc b/tests/unit/libexpr/derived-path.cc index 8a415ab46..1dd61719c 100644 --- a/tests/unit/libexpr/derived-path.cc +++ b/tests/unit/libexpr/derived-path.cc @@ -27,9 +27,9 @@ RC_GTEST_FIXTURE_PROP( prop_opaque_path_round_trip, (const SingleDerivedPath::Opaque & o)) { - auto * v = evaluator.mem.allocValue(); - evaluator.paths.mkStorePathString(o.path, *v); - auto d = state.coerceToSingleDerivedPath(noPos, *v, ""); + Value v; + evaluator.paths.mkStorePathString(o.path, v); + auto d = state.coerceToSingleDerivedPath(noPos, v, ""); RC_ASSERT(SingleDerivedPath { o } == d); } @@ -41,9 +41,9 @@ RC_GTEST_FIXTURE_PROP( prop_derived_path_built_out_path_round_trip, (const SingleDerivedPath::Built & b, const StorePath & outPath)) { - auto * v = evaluator.mem.allocValue(); - state.mkOutputString(*v, b, outPath); - auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, *v, ""); + Value v; + state.mkOutputString(v, b, outPath); + auto [d, _] = state.coerceToSingleDerivedPathUnchecked(noPos, v, ""); RC_ASSERT(SingleDerivedPath { b } == d); }