mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 12:06:01 +01:00
treewide: Replace a lot of std::function with recursive lambdas via 'deducing this'
This is much simpler and has less overhead than a std::function, which does type erasure.
This commit is contained in:
parent
64c55961eb
commit
b9ecd329ae
13 changed files with 50 additions and 81 deletions
|
|
@ -2160,9 +2160,7 @@ void EvalState::forceValueDeep(Value & v)
|
||||||
{
|
{
|
||||||
std::set<const Value *> seen;
|
std::set<const Value *> seen;
|
||||||
|
|
||||||
std::function<void(Value & v)> recurse;
|
auto recurse = [&](this auto & recurse, Value & v) {
|
||||||
|
|
||||||
recurse = [&](Value & v) {
|
|
||||||
if (!seen.insert(&v).second)
|
if (!seen.insert(&v).second)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,7 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va
|
||||||
|
|
||||||
std::istringstream tomlStream(std::string{toml});
|
std::istringstream tomlStream(std::string{toml});
|
||||||
|
|
||||||
auto visit = [&](auto & self, Value & v, toml::value t) -> void {
|
auto visit = [&](this auto & visit, Value & v, toml::value t) -> void {
|
||||||
switch (t.type()) {
|
switch (t.type()) {
|
||||||
case toml::value_t::table: {
|
case toml::value_t::table: {
|
||||||
auto table = toml::get<toml::table>(t);
|
auto table = toml::get<toml::table>(t);
|
||||||
|
|
@ -100,7 +100,7 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va
|
||||||
|
|
||||||
for (auto & elem : table) {
|
for (auto & elem : table) {
|
||||||
forceNoNullByte(elem.first);
|
forceNoNullByte(elem.first);
|
||||||
self(self, attrs.alloc(elem.first), elem.second);
|
visit(attrs.alloc(elem.first), elem.second);
|
||||||
}
|
}
|
||||||
|
|
||||||
v.mkAttrs(attrs);
|
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());
|
auto list = state.buildList(array.size());
|
||||||
for (const auto & [n, v] : enumerate(list))
|
for (const auto & [n, v] : enumerate(list))
|
||||||
self(self, *(v = state.allocValue()), array[n]);
|
visit(*(v = state.allocValue()), array[n]);
|
||||||
v.mkList(list);
|
v.mkList(list);
|
||||||
} break;
|
} break;
|
||||||
case toml::value_t::boolean:
|
case toml::value_t::boolean:
|
||||||
|
|
@ -155,7 +155,6 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va
|
||||||
|
|
||||||
try {
|
try {
|
||||||
visit(
|
visit(
|
||||||
visit,
|
|
||||||
val,
|
val,
|
||||||
toml::parse(
|
toml::parse(
|
||||||
tomlStream,
|
tomlStream,
|
||||||
|
|
|
||||||
|
|
@ -469,41 +469,31 @@ lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef,
|
||||||
|
|
||||||
std::vector<FlakeRef> parents;
|
std::vector<FlakeRef> parents;
|
||||||
|
|
||||||
std::function<void(
|
auto computeLocks = [&](this auto & computeLocks,
|
||||||
const FlakeInputs & flakeInputs,
|
/* The inputs of this node, either from flake.nix or
|
||||||
ref<Node> node,
|
flake.lock. */
|
||||||
const InputAttrPath & inputAttrPathPrefix,
|
const FlakeInputs & flakeInputs,
|
||||||
std::shared_ptr<const Node> oldNode,
|
/* The node whose locks are to be updated.*/
|
||||||
const InputAttrPath & followsPrefix,
|
ref<Node> node,
|
||||||
const SourcePath & sourcePath,
|
/* The path to this node in the lock file graph. */
|
||||||
bool trustLock)>
|
const InputAttrPath & inputAttrPathPrefix,
|
||||||
computeLocks;
|
/* The old node, if any, from which locks can be
|
||||||
|
copied. */
|
||||||
computeLocks = [&](
|
std::shared_ptr<const Node> oldNode,
|
||||||
/* The inputs of this node, either from flake.nix or
|
/* The prefix relative to which 'follows' should be
|
||||||
flake.lock. */
|
interpreted. When a node is initially locked, it's
|
||||||
const FlakeInputs & flakeInputs,
|
relative to the node's flake; when it's already locked,
|
||||||
/* The node whose locks are to be updated.*/
|
it's relative to the root of the lock file. */
|
||||||
ref<Node> node,
|
const InputAttrPath & followsPrefix,
|
||||||
/* The path to this node in the lock file graph. */
|
/* The source path of this node's flake. */
|
||||||
const InputAttrPath & inputAttrPathPrefix,
|
const SourcePath & sourcePath,
|
||||||
/* The old node, if any, from which locks can be
|
bool trustLock) -> void {
|
||||||
copied. */
|
|
||||||
std::shared_ptr<const Node> oldNode,
|
|
||||||
/* The prefix relative to which 'follows' should be
|
|
||||||
interpreted. When a node is initially locked, it's
|
|
||||||
relative to the node's flake; when it's already locked,
|
|
||||||
it's relative to the root of the lock file. */
|
|
||||||
const InputAttrPath & followsPrefix,
|
|
||||||
/* The source path of this node's flake. */
|
|
||||||
const SourcePath & sourcePath,
|
|
||||||
bool trustLock) {
|
|
||||||
debug("computing lock file node '%s'", printInputAttrPath(inputAttrPathPrefix));
|
debug("computing lock file node '%s'", printInputAttrPath(inputAttrPathPrefix));
|
||||||
|
|
||||||
/* Get the overrides (i.e. attributes of the form
|
/* Get the overrides (i.e. attributes of the form
|
||||||
'inputs.nixops.inputs.nixpkgs.url = ...'). */
|
'inputs.nixops.inputs.nixpkgs.url = ...'). */
|
||||||
std::function<void(const FlakeInput & input, const InputAttrPath & prefix)> addOverrides;
|
auto addOverrides =
|
||||||
addOverrides = [&](const FlakeInput & input, const InputAttrPath & prefix) {
|
[&](this auto & addOverrides, const FlakeInput & input, const InputAttrPath & prefix) -> void {
|
||||||
for (auto & [idOverride, inputOverride] : input.overrides) {
|
for (auto & [idOverride, inputOverride] : input.overrides) {
|
||||||
auto inputAttrPath(prefix);
|
auto inputAttrPath(prefix);
|
||||||
inputAttrPath.push_back(idOverride);
|
inputAttrPath.push_back(idOverride);
|
||||||
|
|
|
||||||
|
|
@ -149,9 +149,7 @@ LockFile::LockFile(const fetchers::Settings & fetchSettings, std::string_view co
|
||||||
|
|
||||||
std::map<std::string, ref<Node>> nodeMap;
|
std::map<std::string, ref<Node>> nodeMap;
|
||||||
|
|
||||||
std::function<void(Node & node, const nlohmann::json & jsonNode)> getInputs;
|
auto getInputs = [&](this auto & getInputs, Node & node, const nlohmann::json & jsonNode) -> void {
|
||||||
|
|
||||||
getInputs = [&](Node & node, const nlohmann::json & jsonNode) {
|
|
||||||
if (jsonNode.find("inputs") == jsonNode.end())
|
if (jsonNode.find("inputs") == jsonNode.end())
|
||||||
return;
|
return;
|
||||||
for (auto & i : jsonNode["inputs"].items()) {
|
for (auto & i : jsonNode["inputs"].items()) {
|
||||||
|
|
@ -276,9 +274,7 @@ std::optional<FlakeRef> LockFile::isUnlocked(const fetchers::Settings & fetchSet
|
||||||
{
|
{
|
||||||
std::set<ref<const Node>> nodes;
|
std::set<ref<const Node>> nodes;
|
||||||
|
|
||||||
std::function<void(ref<const Node> node)> visit;
|
auto visit = [&](this auto & visit, ref<const Node> node) -> void {
|
||||||
|
|
||||||
visit = [&](ref<const Node> node) {
|
|
||||||
if (!nodes.insert(node).second)
|
if (!nodes.insert(node).second)
|
||||||
return;
|
return;
|
||||||
for (auto & i : node->inputs)
|
for (auto & i : node->inputs)
|
||||||
|
|
@ -332,9 +328,7 @@ std::map<InputAttrPath, Node::Edge> LockFile::getAllInputs() const
|
||||||
std::set<ref<Node>> done;
|
std::set<ref<Node>> done;
|
||||||
std::map<InputAttrPath, Node::Edge> res;
|
std::map<InputAttrPath, Node::Edge> res;
|
||||||
|
|
||||||
std::function<void(const InputAttrPath & prefix, ref<Node> node)> recurse;
|
auto recurse = [&](this auto & recurse, const InputAttrPath & prefix, ref<Node> node) -> void {
|
||||||
|
|
||||||
recurse = [&](const InputAttrPath & prefix, ref<Node> node) {
|
|
||||||
if (!done.insert(node).second)
|
if (!done.insert(node).second)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,14 @@ namespace nix {
|
||||||
template<typename V>
|
template<typename V>
|
||||||
typename DerivedPathMap<V>::ChildNode & DerivedPathMap<V>::ensureSlot(const SingleDerivedPath & k)
|
typename DerivedPathMap<V>::ChildNode & DerivedPathMap<V>::ensureSlot(const SingleDerivedPath & k)
|
||||||
{
|
{
|
||||||
std::function<ChildNode &(const SingleDerivedPath &)> initIter;
|
auto initIter = [&](this auto & initIter, const auto & k) -> ChildNode & {
|
||||||
initIter = [&](const auto & k) -> auto & {
|
|
||||||
return std::visit(
|
return std::visit(
|
||||||
overloaded{
|
overloaded{
|
||||||
[&](const SingleDerivedPath::Opaque & bo) -> auto & {
|
[&](const SingleDerivedPath::Opaque & bo) -> ChildNode & {
|
||||||
// will not overwrite if already there
|
// will not overwrite if already there
|
||||||
return map[bo.path];
|
return map[bo.path];
|
||||||
},
|
},
|
||||||
[&](const SingleDerivedPath::Built & bfd) -> auto & {
|
[&](const SingleDerivedPath::Built & bfd) -> ChildNode & {
|
||||||
auto & n = initIter(*bfd.drvPath);
|
auto & n = initIter(*bfd.drvPath);
|
||||||
return n.childMap[bfd.output];
|
return n.childMap[bfd.output];
|
||||||
},
|
},
|
||||||
|
|
@ -27,15 +26,14 @@ typename DerivedPathMap<V>::ChildNode & DerivedPathMap<V>::ensureSlot(const Sing
|
||||||
template<typename V>
|
template<typename V>
|
||||||
typename DerivedPathMap<V>::ChildNode * DerivedPathMap<V>::findSlot(const SingleDerivedPath & k)
|
typename DerivedPathMap<V>::ChildNode * DerivedPathMap<V>::findSlot(const SingleDerivedPath & k)
|
||||||
{
|
{
|
||||||
std::function<ChildNode *(const SingleDerivedPath &)> initIter;
|
auto initIter = [&](this auto & initIter, const auto & k) -> ChildNode * {
|
||||||
initIter = [&](const auto & k) {
|
|
||||||
return std::visit(
|
return std::visit(
|
||||||
overloaded{
|
overloaded{
|
||||||
[&](const SingleDerivedPath::Opaque & bo) {
|
[&](const SingleDerivedPath::Opaque & bo) -> ChildNode * {
|
||||||
auto it = map.find(bo.path);
|
auto it = map.find(bo.path);
|
||||||
return it != map.end() ? &it->second : nullptr;
|
return it != map.end() ? &it->second : nullptr;
|
||||||
},
|
},
|
||||||
[&](const SingleDerivedPath::Built & bfd) {
|
[&](const SingleDerivedPath::Built & bfd) -> ChildNode * {
|
||||||
auto * n = initIter(*bfd.drvPath);
|
auto * n = initIter(*bfd.drvPath);
|
||||||
if (!n)
|
if (!n)
|
||||||
return (ChildNode *) nullptr;
|
return (ChildNode *) nullptr;
|
||||||
|
|
|
||||||
|
|
@ -146,9 +146,7 @@ struct NarAccessor : public SourceAccessor
|
||||||
{
|
{
|
||||||
using json = nlohmann::json;
|
using json = nlohmann::json;
|
||||||
|
|
||||||
std::function<void(NarMember &, const json &)> recurse;
|
auto recurse = [&](this auto & recurse, NarMember & member, const json & v) -> void {
|
||||||
|
|
||||||
recurse = [&](NarMember & member, const json & v) {
|
|
||||||
std::string type = v["type"];
|
std::string type = v["type"];
|
||||||
|
|
||||||
if (type == "directory") {
|
if (type == "directory") {
|
||||||
|
|
|
||||||
|
|
@ -284,8 +284,7 @@ TEST_F(GitTest, both_roundrip)
|
||||||
|
|
||||||
MemorySink sinkFiles2{*files2};
|
MemorySink sinkFiles2{*files2};
|
||||||
|
|
||||||
std::function<void(const CanonPath, const Hash &, BlobMode)> mkSinkHook;
|
auto mkSinkHook = [&](this auto & mkSinkHook, auto prefix, auto & hash, auto blobMode) -> void {
|
||||||
mkSinkHook = [&](auto prefix, auto & hash, auto blobMode) {
|
|
||||||
StringSource in{cas[hash]};
|
StringSource in{cas[hash]};
|
||||||
parse(
|
parse(
|
||||||
sinkFiles2,
|
sinkFiles2,
|
||||||
|
|
|
||||||
|
|
@ -14,9 +14,7 @@ std::vector<T> topoSort(
|
||||||
std::vector<T> sorted;
|
std::vector<T> sorted;
|
||||||
decltype(items) visited, parents;
|
decltype(items) visited, parents;
|
||||||
|
|
||||||
std::function<void(const T & path, const T * parent)> dfsVisit;
|
auto dfsVisit = [&](this auto & dfsVisit, const T & path, const T * parent) -> void {
|
||||||
|
|
||||||
dfsVisit = [&](const T & path, const T * parent) {
|
|
||||||
if (parents.count(path))
|
if (parents.count(path))
|
||||||
throw makeCycleError(path, *parent);
|
throw makeCycleError(path, *parent);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,9 +85,8 @@ struct CmdEval : MixJSON, InstallableValueCommand, MixReadOnlyOption
|
||||||
if (pathExists(*writeTo))
|
if (pathExists(*writeTo))
|
||||||
throw Error("path '%s' already exists", writeTo->string());
|
throw Error("path '%s' already exists", writeTo->string());
|
||||||
|
|
||||||
std::function<void(Value & v, const PosIdx pos, const std::filesystem::path & path)> recurse;
|
auto recurse =
|
||||||
|
[&](this auto & recurse, Value & v, const PosIdx pos, const std::filesystem::path & path) -> void {
|
||||||
recurse = [&](Value & v, const PosIdx pos, const std::filesystem::path & path) {
|
|
||||||
state->forceValue(v, pos);
|
state->forceValue(v, pos);
|
||||||
if (v.type() == nString)
|
if (v.type() == nString)
|
||||||
// FIXME: disallow strings with contexts?
|
// FIXME: disallow strings with contexts?
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,7 @@ struct CmdFlakePrefetchInputs : FlakeCommand
|
||||||
|
|
||||||
std::atomic<size_t> nrFailed{0};
|
std::atomic<size_t> nrFailed{0};
|
||||||
|
|
||||||
std::function<void(const Node & node)> visit;
|
auto visit = [&](this auto & visit, const Node & node) -> void {
|
||||||
visit = [&](const Node & node) {
|
|
||||||
if (!state_.lock()->done.insert(&node).second)
|
if (!state_.lock()->done.insert(&node).second)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -269,9 +269,7 @@ struct CmdFlakeMetadata : FlakeCommand, MixJSON
|
||||||
|
|
||||||
std::set<ref<Node>> visited;
|
std::set<ref<Node>> visited;
|
||||||
|
|
||||||
std::function<void(const Node & node, const std::string & prefix)> recurse;
|
auto recurse = [&](this auto & recurse, const Node & node, const std::string & prefix) -> void {
|
||||||
|
|
||||||
recurse = [&](const Node & node, const std::string & prefix) {
|
|
||||||
for (const auto & [i, input] : enumerate(node.inputs)) {
|
for (const auto & [i, input] : enumerate(node.inputs)) {
|
||||||
bool last = i + 1 == node.inputs.size();
|
bool last = i + 1 == node.inputs.size();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -90,10 +90,10 @@ struct CmdSearch : InstallableValueCommand, MixJSON
|
||||||
|
|
||||||
uint64_t results = 0;
|
uint64_t results = 0;
|
||||||
|
|
||||||
std::function<void(eval_cache::AttrCursor & cursor, const std::vector<Symbol> & attrPath, bool initialRecurse)>
|
auto visit = [&](this auto & visit,
|
||||||
visit;
|
eval_cache::AttrCursor & cursor,
|
||||||
|
const std::vector<Symbol> & attrPath,
|
||||||
visit = [&](eval_cache::AttrCursor & cursor, const std::vector<Symbol> & attrPath, bool initialRecurse) {
|
bool initialRecurse) -> void {
|
||||||
auto attrPathS = state->symbols.resolve(attrPath);
|
auto attrPathS = state->symbols.resolve(attrPath);
|
||||||
|
|
||||||
Activity act(*logger, lvlInfo, actUnknown, fmt("evaluating '%s'", concatStringsSep(".", attrPathS)));
|
Activity act(*logger, lvlInfo, actUnknown, fmt("evaluating '%s'", concatStringsSep(".", attrPathS)));
|
||||||
|
|
|
||||||
|
|
@ -160,16 +160,15 @@ struct CmdWhyDepends : SourceExprCommand, MixOperateOnOptions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct BailOut
|
||||||
|
{};
|
||||||
|
|
||||||
/* Print the subgraph of nodes that have 'dependency' in their
|
/* Print the subgraph of nodes that have 'dependency' in their
|
||||||
closure (i.e., that have a non-infinite distance to
|
closure (i.e., that have a non-infinite distance to
|
||||||
'dependency'). Print every edge on a path between `package`
|
'dependency'). Print every edge on a path between `package`
|
||||||
and `dependency`. */
|
and `dependency`. */
|
||||||
std::function<void(Node &, const std::string &, const std::string &)> printNode;
|
auto printNode =
|
||||||
|
[&](this auto & printNode, Node & node, const std::string & firstPad, const std::string & tailPad) -> void {
|
||||||
struct BailOut
|
|
||||||
{};
|
|
||||||
|
|
||||||
printNode = [&](Node & node, const std::string & firstPad, const std::string & tailPad) {
|
|
||||||
assert(node.dist != inf);
|
assert(node.dist != inf);
|
||||||
if (precise) {
|
if (precise) {
|
||||||
logger->cout(
|
logger->cout(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue