diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index a6973f590..8a03084ee 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -2160,30 +2160,28 @@ void EvalState::forceValueDeep(Value & v) { std::set seen; - std::function recurse; - - recurse = [&](Value & v) { + [&, &state(*this)](this const auto & recurse, Value & v) { if (!seen.insert(&v).second) return; - forceValue(v, v.determinePos(noPos)); + state.forceValue(v, v.determinePos(noPos)); if (v.type() == nAttrs) { for (auto & i : *v.attrs()) try { // If the value is a thunk, we're evaling. Otherwise no trace necessary. - auto dts = debugRepl && i.value->isThunk() ? makeDebugTraceStacker( - *this, - *i.value->thunk().expr, - *i.value->thunk().env, - i.pos, - "while evaluating the attribute '%1%'", - symbols[i.name]) - : nullptr; + auto dts = state.debugRepl && i.value->isThunk() ? makeDebugTraceStacker( + state, + *i.value->thunk().expr, + *i.value->thunk().env, + i.pos, + "while evaluating the attribute '%1%'", + state.symbols[i.name]) + : nullptr; recurse(*i.value); } catch (Error & e) { - addErrorTrace(e, i.pos, "while evaluating the attribute '%1%'", symbols[i.name]); + state.addErrorTrace(e, i.pos, "while evaluating the attribute '%1%'", state.symbols[i.name]); throw; } } @@ -2192,9 +2190,7 @@ void EvalState::forceValueDeep(Value & v) for (auto v2 : v.listView()) recurse(*v2); } - }; - - recurse(v); + }(v); } NixInt EvalState::forceInt(Value & v, const PosIdx pos, std::string_view errorCtx) diff --git a/src/libexpr/primops/fromTOML.cc b/src/libexpr/primops/fromTOML.cc index d2f91a75b..0d165f5c3 100644 --- a/src/libexpr/primops/fromTOML.cc +++ b/src/libexpr/primops/fromTOML.cc @@ -92,7 +92,7 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va std::istringstream tomlStream(std::string{toml}); - auto visit = [&](auto & self, Value & v, toml::value t) -> void { + auto visit = [&](this auto & self, Value & v, toml::value t) -> void { switch (t.type()) { case toml::value_t::table: { auto table = toml::get(t); @@ -100,7 +100,7 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va for (auto & elem : table) { forceNoNullByte(elem.first); - self(self, attrs.alloc(elem.first), elem.second); + self(attrs.alloc(elem.first), elem.second); } v.mkAttrs(attrs); @@ -110,7 +110,7 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va auto list = state.buildList(array.size()); for (const auto & [n, v] : enumerate(list)) - self(self, *(v = state.allocValue()), array[n]); + self(*(v = state.allocValue()), array[n]); v.mkList(list); } break; case toml::value_t::boolean: @@ -155,7 +155,6 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va try { visit( - visit, val, toml::parse( tomlStream, diff --git a/src/libexpr/value/context.cc b/src/libexpr/value/context.cc index 6eb313211..dcc577f05 100644 --- a/src/libexpr/value/context.cc +++ b/src/libexpr/value/context.cc @@ -9,8 +9,7 @@ NixStringContextElem NixStringContextElem::parse(std::string_view s0, const Expe { std::string_view s = s0; - std::function parseRest; - parseRest = [&]() -> SingleDerivedPath { + auto parseRest = [&](this auto & parseRest) -> SingleDerivedPath { // Case on whether there is a '!' size_t index = s.find("!"); if (index == std::string_view::npos) { diff --git a/src/libflake/flake.cc b/src/libflake/flake.cc index 8e7e2be26..2aec0fac4 100644 --- a/src/libflake/flake.cc +++ b/src/libflake/flake.cc @@ -502,8 +502,8 @@ lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef, /* Get the overrides (i.e. attributes of the form 'inputs.nixops.inputs.nixpkgs.url = ...'). */ - std::function addOverrides; - addOverrides = [&](const FlakeInput & input, const InputAttrPath & prefix) { + auto addOverrides = + [&](this const auto & addOverrides, const FlakeInput & input, const InputAttrPath & prefix) -> void { for (auto & [idOverride, inputOverride] : input.overrides) { auto inputAttrPath(prefix); inputAttrPath.push_back(idOverride); diff --git a/src/libflake/lockfile.cc b/src/libflake/lockfile.cc index d0d339f9f..ecad5df6f 100644 --- a/src/libflake/lockfile.cc +++ b/src/libflake/lockfile.cc @@ -147,11 +147,10 @@ LockFile::LockFile(const fetchers::Settings & fetchSettings, std::string_view co if (version < 5 || version > 7) throw Error("lock file '%s' has unsupported version %d", path, version); - std::map> nodeMap; + std::string rootKey = json["root"]; + std::map> nodeMap{{rootKey, root}}; - std::function getInputs; - - getInputs = [&](Node & node, const nlohmann::json & jsonNode) { + [&](this const auto & getInputs, Node & node, const nlohmann::json & jsonNode) { if (jsonNode.find("inputs") == jsonNode.end()) return; for (auto & i : jsonNode["inputs"].items()) { @@ -179,11 +178,7 @@ LockFile::LockFile(const fetchers::Settings & fetchSettings, std::string_view co throw Error("lock file contains cycle to root node"); } } - }; - - std::string rootKey = json["root"]; - nodeMap.insert_or_assign(rootKey, root); - getInputs(*root, json["nodes"][rootKey]); + }(*root, json["nodes"][rootKey]); // FIXME: check that there are no cycles in version >= 7. Cycles // between inputs are only possible using 'follows' indirections. @@ -197,9 +192,7 @@ std::pair LockFile::toJSON() const KeyMap nodeKeys; boost::unordered_flat_set keys; - std::function node)> dumpNode; - - dumpNode = [&](std::string key, ref node) -> std::string { + auto dumpNode = [&](this auto & dumpNode, std::string key, ref node) -> std::string { auto k = nodeKeys.find(node); if (k != nodeKeys.end()) return k->second; @@ -276,17 +269,13 @@ std::optional LockFile::isUnlocked(const fetchers::Settings & fetchSet { std::set> nodes; - std::function node)> visit; - - visit = [&](ref node) { + [&](this const auto & visit, ref node) { if (!nodes.insert(node).second) return; for (auto & i : node->inputs) if (auto child = std::get_if<0>(&i.second)) visit(*child); - }; - - visit(root); + }(root); /* Return whether the input is either locked, or, if `allow-dirty-locks` is enabled, it has a NAR hash. In the @@ -332,9 +321,7 @@ std::map LockFile::getAllInputs() const std::set> done; std::map res; - std::function node)> recurse; - - recurse = [&](const InputAttrPath & prefix, ref node) { + [&](this const auto & recurse, const InputAttrPath & prefix, ref node) { if (!done.insert(node).second) return; @@ -345,9 +332,7 @@ std::map LockFile::getAllInputs() const if (auto child = std::get_if<0>(&input)) recurse(inputAttrPath, *child); } - }; - - recurse({}, root); + }({}, root); return res; } diff --git a/src/libstore/derivations.cc b/src/libstore/derivations.cc index f44bf3e70..b7de615fb 100644 --- a/src/libstore/derivations.cc +++ b/src/libstore/derivations.cc @@ -1391,8 +1391,7 @@ void adl_serializer::to_json(json & res, const Derivation & d) } { - std::function::ChildNode &)> doInput; - doInput = [&](const auto & inputNode) { + auto doInput = [&](this const auto & doInput, const auto & inputNode) -> nlohmann::json { auto value = nlohmann::json::object(); value["outputs"] = inputNode.value; { @@ -1454,8 +1453,7 @@ Derivation adl_serializer::from_json(const json & _json, const Exper } try { - std::function::ChildNode(const nlohmann::json &)> doInput; - doInput = [&](const auto & _json) { + auto doInput = [&](this const auto & doInput, const auto & _json) -> DerivedPathMap::ChildNode { auto & json = getObject(_json); DerivedPathMap::ChildNode node; node.value = getStringSet(valueAt(json, "outputs")); diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index a31d149c2..8b2a7287e 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -126,13 +126,13 @@ MissingPaths Store::queryMissing(const std::vector & targets) std::function doPath; - std::function, const DerivedPathMap::ChildNode &)> enqueueDerivedPaths; - - enqueueDerivedPaths = [&](ref inputDrv, const DerivedPathMap::ChildNode & inputNode) { + auto enqueueDerivedPaths = [&](this auto self, + ref inputDrv, + const DerivedPathMap::ChildNode & inputNode) -> void { if (!inputNode.value.empty()) pool.enqueue(std::bind(doPath, DerivedPath::Built{inputDrv, inputNode.value})); for (const auto & [outputName, childNode] : inputNode.childMap) - enqueueDerivedPaths(make_ref(SingleDerivedPath::Built{inputDrv, outputName}), childNode); + self(make_ref(SingleDerivedPath::Built{inputDrv, outputName}), childNode); }; auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) { @@ -350,9 +350,9 @@ drvOutputReferences(Store & store, const Derivation & drv, const StorePath & out std::set inputRealisations; - std::function::ChildNode &)> accumRealisations; - - accumRealisations = [&](const StorePath & inputDrv, const DerivedPathMap::ChildNode & inputNode) { + auto accumRealisations = [&](this auto & self, + const StorePath & inputDrv, + const DerivedPathMap::ChildNode & inputNode) -> void { if (!inputNode.value.empty()) { auto outputHashes = staticOutputHashes(evalStore, evalStore.readDerivation(inputDrv)); for (const auto & outputName : inputNode.value) { @@ -372,7 +372,7 @@ drvOutputReferences(Store & store, const Derivation & drv, const StorePath & out auto d = makeConstantStorePathRef(inputDrv); for (const auto & [outputName, childNode] : inputNode.childMap) { SingleDerivedPath next = SingleDerivedPath::Built{d, outputName}; - accumRealisations( + self( // TODO deep resolutions for dynamic derivations, issue #8947, would go here. resolveDerivedPath(store, next, evalStore_), childNode); diff --git a/src/libstore/nar-accessor.cc b/src/libstore/nar-accessor.cc index f0882d52d..640b77540 100644 --- a/src/libstore/nar-accessor.cc +++ b/src/libstore/nar-accessor.cc @@ -144,11 +144,7 @@ struct NarAccessor : public SourceAccessor NarAccessor(const nlohmann::json & listing, GetNarBytes getNarBytes) : getNarBytes(getNarBytes) { - using json = nlohmann::json; - - std::function recurse; - - recurse = [&](NarMember & member, const json & v) { + [&](this const auto & recurse, NarMember & member, const nlohmann::json & v) -> void { std::string type = v["type"]; if (type == "directory") { @@ -167,9 +163,7 @@ struct NarAccessor : public SourceAccessor member.target = v.value("target", ""); } else return; - }; - - recurse(root, listing); + }(root, listing); } NarMember * find(const CanonPath & path) diff --git a/src/libutil/archive.cc b/src/libutil/archive.cc index 73ec0cab7..737d9b2fe 100644 --- a/src/libutil/archive.cc +++ b/src/libutil/archive.cc @@ -47,12 +47,12 @@ void SourceAccessor::dumpPath(const CanonPath & path, Sink & sink, PathFilter & writePadding(*size, sink); }; - std::function dump; + sink << narVersionMagic1; - dump = [&](const CanonPath & path) { + [&, &this_(*this)](this const auto & dump, const CanonPath & path) -> void { checkInterrupt(); - auto st = lstat(path); + auto st = this_.lstat(path); sink << "("; @@ -69,7 +69,7 @@ void SourceAccessor::dumpPath(const CanonPath & path, Sink & sink, PathFilter & /* If we're on a case-insensitive system like macOS, undo the case hack applied by restorePath(). */ StringMap unhacked; - for (auto & i : readDirectory(path)) + for (auto & i : this_.readDirectory(path)) if (archiveSettings.useCaseHack) { std::string name(i.first); size_t pos = i.first.find(caseHackSuffix); @@ -92,16 +92,13 @@ void SourceAccessor::dumpPath(const CanonPath & path, Sink & sink, PathFilter & } else if (st.type == tSymlink) - sink << "type" << "symlink" << "target" << readLink(path); + sink << "type" << "symlink" << "target" << this_.readLink(path); else throw Error("file '%s' has an unsupported type", path); sink << ")"; - }; - - sink << narVersionMagic1; - dump(path); + }(path); } time_t dumpPathAndGetMtime(const Path & path, Sink & sink, PathFilter & filter) diff --git a/src/libutil/include/nix/util/closure.hh b/src/libutil/include/nix/util/closure.hh index d55d52c87..9e37b4cfb 100644 --- a/src/libutil/include/nix/util/closure.hh +++ b/src/libutil/include/nix/util/closure.hh @@ -24,11 +24,9 @@ void computeClosure(const set startElts, set & res, GetEdgesAsync getEd Sync state_(State{0, res, 0}); - std::function enqueue; - std::condition_variable done; - enqueue = [&](const T & current) -> void { + auto enqueue = [&](this auto & enqueue, const T & current) -> void { { auto state(state_.lock()); if (state->exc) diff --git a/src/libutil/include/nix/util/topo-sort.hh b/src/libutil/include/nix/util/topo-sort.hh index 9f403e2e6..aaf5dff16 100644 --- a/src/libutil/include/nix/util/topo-sort.hh +++ b/src/libutil/include/nix/util/topo-sort.hh @@ -14,9 +14,7 @@ std::vector topoSort( std::vector sorted; decltype(items) visited, parents; - std::function dfsVisit; - - dfsVisit = [&](const T & path, const T * parent) { + auto dfsVisit = [&](this auto & dfsVisit, const T & path, const T * parent) { if (parents.count(path)) throw makeCycleError(path, *parent); diff --git a/src/nix/eval.cc b/src/nix/eval.cc index 10d0a1841..584b2122f 100644 --- a/src/nix/eval.cc +++ b/src/nix/eval.cc @@ -85,9 +85,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption if (pathExists(*writeTo)) throw Error("path '%s' already exists", writeTo->string()); - std::function recurse; - - recurse = [&](Value & v, const PosIdx pos, const std::filesystem::path & path) { + [&](this const auto & recurse, Value & v, const PosIdx pos, const std::filesystem::path & path) -> void { state->forceValue(v, pos); if (v.type() == nString) // FIXME: disallow strings with contexts? @@ -111,9 +109,7 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption } else state->error("value at '%s' is not a string or an attribute set", state->positions[pos]) .debugThrow(); - }; - - recurse(*v, pos, *writeTo); + }(*v, pos, *writeTo); } else if (raw) { diff --git a/src/nix/flake-prefetch-inputs.cc b/src/nix/flake-prefetch-inputs.cc index 096eaf539..2a3e067c6 100644 --- a/src/nix/flake-prefetch-inputs.cc +++ b/src/nix/flake-prefetch-inputs.cc @@ -38,8 +38,7 @@ struct CmdFlakePrefetchInputs : FlakeCommand std::atomic nrFailed{0}; - std::function visit; - visit = [&](const Node & node) { + auto visit = [&](this const auto & visit, const Node & node) { if (!state_.lock()->done.insert(&node).second) return; diff --git a/src/nix/flake.cc b/src/nix/flake.cc index 04d4ec8eb..a7e7d0039 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -267,11 +267,9 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON if (!lockedFlake.lockFile.root->inputs.empty()) logger->cout(ANSI_BOLD "Inputs:" ANSI_NORMAL); - std::set> visited; + std::set> visited{lockedFlake.lockFile.root}; - std::function recurse; - - recurse = [&](const Node & node, const std::string & prefix) { + [&](this const auto & recurse, const Node & node, const std::string & prefix) -> void { for (const auto & [i, input] : enumerate(node.inputs)) { bool last = i + 1 == node.inputs.size(); @@ -298,10 +296,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON printInputAttrPath(*follows)); } } - }; - - visited.insert(lockedFlake.lockFile.root); - recurse(*lockedFlake.lockFile.root, ""); + }(*lockedFlake.lockFile.root, ""); } } }; @@ -884,8 +879,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand std::vector changedFiles; std::vector conflictedFiles; - std::function copyDir; - copyDir = [&](const SourcePath & from, const std::filesystem::path & to) { + [&](this const auto & copyDir, const SourcePath & from, const std::filesystem::path & to) -> void { createDirs(to); for (auto & [name, entry] : from.readDirectory()) { @@ -935,9 +929,7 @@ struct CmdFlakeInitCommon : virtual Args, EvalCommand changedFiles.push_back(to2); notice("wrote: %s", to2); } - }; - - copyDir(templateDir, flakeDir); + }(templateDir, flakeDir); if (!changedFiles.empty() && std::filesystem::exists(std::filesystem::path{flakeDir} / ".git")) { Strings args = {"-C", flakeDir, "add", "--intent-to-add", "--force", "--"}; diff --git a/src/nix/nix-build/nix-build.cc b/src/nix/nix-build/nix-build.cc index 8aced503b..ab65fba7e 100644 --- a/src/nix/nix-build/nix-build.cc +++ b/src/nix/nix-build/nix-build.cc @@ -410,8 +410,7 @@ static void main_nix_build(int argc, char ** argv) Value vRoot; state->eval(e, vRoot); - std::function takesNixShellAttr; - takesNixShellAttr = [&](const Value & v) { + auto takesNixShellAttr = [&](const Value & v) { if (!isNixShell) { return false; } @@ -490,10 +489,9 @@ static void main_nix_build(int argc, char ** argv) } } - std::function, const DerivedPathMap::ChildNode &)> accumDerivedPath; - - accumDerivedPath = [&](ref inputDrv, - const DerivedPathMap::ChildNode & inputNode) { + auto accumDerivedPath = [&](this auto & self, + ref inputDrv, + const DerivedPathMap::ChildNode & inputNode) -> void { if (!inputNode.value.empty()) pathsToBuild.push_back( DerivedPath::Built{ @@ -501,8 +499,7 @@ static void main_nix_build(int argc, char ** argv) .outputs = OutputsSpec::Names{inputNode.value}, }); for (const auto & [outputName, childNode] : inputNode.childMap) - accumDerivedPath( - make_ref(SingleDerivedPath::Built{inputDrv, outputName}), childNode); + self(make_ref(SingleDerivedPath::Built{inputDrv, outputName}), childNode); }; // Build or fetch all dependencies of the derivation.