Skip to content

Commit 1507843

Browse files
edolstraxokdvium
authored andcommitted
Cleanup: Use C++23 "explicit this" for recursive lambdas
Try to pass by reference where possible. Co-authored-by: Sergei Zimmerman <[email protected]>
1 parent 3b2186e commit 1507843

File tree

15 files changed

+60
-112
lines changed

15 files changed

+60
-112
lines changed

src/libexpr/eval.cc

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2160,30 +2160,28 @@ void EvalState::forceValueDeep(Value & v)
21602160
{
21612161
std::set<const Value *> seen;
21622162

2163-
std::function<void(Value & v)> recurse;
2164-
2165-
recurse = [&](Value & v) {
2163+
[&, &state(*this)](this const auto & recurse, Value & v) {
21662164
if (!seen.insert(&v).second)
21672165
return;
21682166

2169-
forceValue(v, v.determinePos(noPos));
2167+
state.forceValue(v, v.determinePos(noPos));
21702168

21712169
if (v.type() == nAttrs) {
21722170
for (auto & i : *v.attrs())
21732171
try {
21742172
// If the value is a thunk, we're evaling. Otherwise no trace necessary.
2175-
auto dts = debugRepl && i.value->isThunk() ? makeDebugTraceStacker(
2176-
*this,
2177-
*i.value->thunk().expr,
2178-
*i.value->thunk().env,
2179-
i.pos,
2180-
"while evaluating the attribute '%1%'",
2181-
symbols[i.name])
2182-
: nullptr;
2173+
auto dts = state.debugRepl && i.value->isThunk() ? makeDebugTraceStacker(
2174+
state,
2175+
*i.value->thunk().expr,
2176+
*i.value->thunk().env,
2177+
i.pos,
2178+
"while evaluating the attribute '%1%'",
2179+
state.symbols[i.name])
2180+
: nullptr;
21832181

21842182
recurse(*i.value);
21852183
} catch (Error & e) {
2186-
addErrorTrace(e, i.pos, "while evaluating the attribute '%1%'", symbols[i.name]);
2184+
state.addErrorTrace(e, i.pos, "while evaluating the attribute '%1%'", state.symbols[i.name]);
21872185
throw;
21882186
}
21892187
}
@@ -2192,9 +2190,7 @@ void EvalState::forceValueDeep(Value & v)
21922190
for (auto v2 : v.listView())
21932191
recurse(*v2);
21942192
}
2195-
};
2196-
2197-
recurse(v);
2193+
}(v);
21982194
}
21992195

22002196
NixInt EvalState::forceInt(Value & v, const PosIdx pos, std::string_view errorCtx)

src/libexpr/primops/fromTOML.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,15 +92,15 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va
9292

9393
std::istringstream tomlStream(std::string{toml});
9494

95-
auto visit = [&](auto & self, Value & v, toml::value t) -> void {
95+
auto visit = [&](this auto & self, Value & v, toml::value t) -> void {
9696
switch (t.type()) {
9797
case toml::value_t::table: {
9898
auto table = toml::get<toml::table>(t);
9999
auto attrs = state.buildBindings(table.size());
100100

101101
for (auto & elem : table) {
102102
forceNoNullByte(elem.first);
103-
self(self, attrs.alloc(elem.first), elem.second);
103+
self(attrs.alloc(elem.first), elem.second);
104104
}
105105

106106
v.mkAttrs(attrs);
@@ -110,7 +110,7 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va
110110

111111
auto list = state.buildList(array.size());
112112
for (const auto & [n, v] : enumerate(list))
113-
self(self, *(v = state.allocValue()), array[n]);
113+
self(*(v = state.allocValue()), array[n]);
114114
v.mkList(list);
115115
} break;
116116
case toml::value_t::boolean:
@@ -155,7 +155,6 @@ static void prim_fromTOML(EvalState & state, const PosIdx pos, Value ** args, Va
155155

156156
try {
157157
visit(
158-
visit,
159158
val,
160159
toml::parse(
161160
tomlStream,

src/libexpr/value/context.cc

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ NixStringContextElem NixStringContextElem::parse(std::string_view s0, const Expe
99
{
1010
std::string_view s = s0;
1111

12-
std::function<SingleDerivedPath()> parseRest;
13-
parseRest = [&]() -> SingleDerivedPath {
12+
auto parseRest = [&](this auto & parseRest) -> SingleDerivedPath {
1413
// Case on whether there is a '!'
1514
size_t index = s.find("!");
1615
if (index == std::string_view::npos) {

src/libflake/flake.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -502,8 +502,8 @@ lockFlake(const Settings & settings, EvalState & state, const FlakeRef & topRef,
502502

503503
/* Get the overrides (i.e. attributes of the form
504504
'inputs.nixops.inputs.nixpkgs.url = ...'). */
505-
std::function<void(const FlakeInput & input, const InputAttrPath & prefix)> addOverrides;
506-
addOverrides = [&](const FlakeInput & input, const InputAttrPath & prefix) {
505+
auto addOverrides =
506+
[&](this const auto & addOverrides, const FlakeInput & input, const InputAttrPath & prefix) -> void {
507507
for (auto & [idOverride, inputOverride] : input.overrides) {
508508
auto inputAttrPath(prefix);
509509
inputAttrPath.push_back(idOverride);

src/libflake/lockfile.cc

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,10 @@ LockFile::LockFile(const fetchers::Settings & fetchSettings, std::string_view co
147147
if (version < 5 || version > 7)
148148
throw Error("lock file '%s' has unsupported version %d", path, version);
149149

150-
std::map<std::string, ref<Node>> nodeMap;
151-
152-
std::function<void(Node & node, const nlohmann::json & jsonNode)> getInputs;
150+
std::string rootKey = json["root"];
151+
std::map<std::string, ref<Node>> nodeMap{{rootKey, root}};
153152

154-
getInputs = [&](Node & node, const nlohmann::json & jsonNode) {
153+
[&](this const auto & getInputs, Node & node, const nlohmann::json & jsonNode) {
155154
if (jsonNode.find("inputs") == jsonNode.end())
156155
return;
157156
for (auto & i : jsonNode["inputs"].items()) {
@@ -179,11 +178,7 @@ LockFile::LockFile(const fetchers::Settings & fetchSettings, std::string_view co
179178
throw Error("lock file contains cycle to root node");
180179
}
181180
}
182-
};
183-
184-
std::string rootKey = json["root"];
185-
nodeMap.insert_or_assign(rootKey, root);
186-
getInputs(*root, json["nodes"][rootKey]);
181+
}(*root, json["nodes"][rootKey]);
187182

188183
// FIXME: check that there are no cycles in version >= 7. Cycles
189184
// between inputs are only possible using 'follows' indirections.
@@ -197,9 +192,7 @@ std::pair<nlohmann::json, LockFile::KeyMap> LockFile::toJSON() const
197192
KeyMap nodeKeys;
198193
boost::unordered_flat_set<std::string> keys;
199194

200-
std::function<std::string(const std::string & key, ref<const Node> node)> dumpNode;
201-
202-
dumpNode = [&](std::string key, ref<const Node> node) -> std::string {
195+
auto dumpNode = [&](this auto & dumpNode, std::string key, ref<const Node> node) -> std::string {
203196
auto k = nodeKeys.find(node);
204197
if (k != nodeKeys.end())
205198
return k->second;
@@ -276,17 +269,13 @@ std::optional<FlakeRef> LockFile::isUnlocked(const fetchers::Settings & fetchSet
276269
{
277270
std::set<ref<const Node>> nodes;
278271

279-
std::function<void(ref<const Node> node)> visit;
280-
281-
visit = [&](ref<const Node> node) {
272+
[&](this const auto & visit, ref<const Node> node) {
282273
if (!nodes.insert(node).second)
283274
return;
284275
for (auto & i : node->inputs)
285276
if (auto child = std::get_if<0>(&i.second))
286277
visit(*child);
287-
};
288-
289-
visit(root);
278+
}(root);
290279

291280
/* Return whether the input is either locked, or, if
292281
`allow-dirty-locks` is enabled, it has a NAR hash. In the
@@ -332,9 +321,7 @@ std::map<InputAttrPath, Node::Edge> LockFile::getAllInputs() const
332321
std::set<ref<Node>> done;
333322
std::map<InputAttrPath, Node::Edge> res;
334323

335-
std::function<void(const InputAttrPath & prefix, ref<Node> node)> recurse;
336-
337-
recurse = [&](const InputAttrPath & prefix, ref<Node> node) {
324+
[&](this const auto & recurse, const InputAttrPath & prefix, ref<Node> node) {
338325
if (!done.insert(node).second)
339326
return;
340327

@@ -345,9 +332,7 @@ std::map<InputAttrPath, Node::Edge> LockFile::getAllInputs() const
345332
if (auto child = std::get_if<0>(&input))
346333
recurse(inputAttrPath, *child);
347334
}
348-
};
349-
350-
recurse({}, root);
335+
}({}, root);
351336

352337
return res;
353338
}

src/libstore/derivations.cc

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,8 +1391,7 @@ void adl_serializer<Derivation>::to_json(json & res, const Derivation & d)
13911391
}
13921392

13931393
{
1394-
std::function<nlohmann::json(const DerivedPathMap<StringSet>::ChildNode &)> doInput;
1395-
doInput = [&](const auto & inputNode) {
1394+
auto doInput = [&](this const auto & doInput, const auto & inputNode) -> nlohmann::json {
13961395
auto value = nlohmann::json::object();
13971396
value["outputs"] = inputNode.value;
13981397
{
@@ -1454,8 +1453,7 @@ Derivation adl_serializer<Derivation>::from_json(const json & _json, const Exper
14541453
}
14551454

14561455
try {
1457-
std::function<DerivedPathMap<StringSet>::ChildNode(const nlohmann::json &)> doInput;
1458-
doInput = [&](const auto & _json) {
1456+
auto doInput = [&](this const auto & doInput, const auto & _json) -> DerivedPathMap<StringSet>::ChildNode {
14591457
auto & json = getObject(_json);
14601458
DerivedPathMap<StringSet>::ChildNode node;
14611459
node.value = getStringSet(valueAt(json, "outputs"));

src/libstore/misc.cc

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,13 @@ MissingPaths Store::queryMissing(const std::vector<DerivedPath> & targets)
126126

127127
std::function<void(DerivedPath)> doPath;
128128

129-
std::function<void(ref<SingleDerivedPath>, const DerivedPathMap<StringSet>::ChildNode &)> enqueueDerivedPaths;
130-
131-
enqueueDerivedPaths = [&](ref<SingleDerivedPath> inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
129+
auto enqueueDerivedPaths = [&](this auto self,
130+
ref<SingleDerivedPath> inputDrv,
131+
const DerivedPathMap<StringSet>::ChildNode & inputNode) -> void {
132132
if (!inputNode.value.empty())
133133
pool.enqueue(std::bind(doPath, DerivedPath::Built{inputDrv, inputNode.value}));
134134
for (const auto & [outputName, childNode] : inputNode.childMap)
135-
enqueueDerivedPaths(make_ref<SingleDerivedPath>(SingleDerivedPath::Built{inputDrv, outputName}), childNode);
135+
self(make_ref<SingleDerivedPath>(SingleDerivedPath::Built{inputDrv, outputName}), childNode);
136136
};
137137

138138
auto mustBuildDrv = [&](const StorePath & drvPath, const Derivation & drv) {
@@ -350,9 +350,9 @@ drvOutputReferences(Store & store, const Derivation & drv, const StorePath & out
350350

351351
std::set<Realisation> inputRealisations;
352352

353-
std::function<void(const StorePath &, const DerivedPathMap<StringSet>::ChildNode &)> accumRealisations;
354-
355-
accumRealisations = [&](const StorePath & inputDrv, const DerivedPathMap<StringSet>::ChildNode & inputNode) {
353+
auto accumRealisations = [&](this auto & self,
354+
const StorePath & inputDrv,
355+
const DerivedPathMap<StringSet>::ChildNode & inputNode) -> void {
356356
if (!inputNode.value.empty()) {
357357
auto outputHashes = staticOutputHashes(evalStore, evalStore.readDerivation(inputDrv));
358358
for (const auto & outputName : inputNode.value) {
@@ -372,7 +372,7 @@ drvOutputReferences(Store & store, const Derivation & drv, const StorePath & out
372372
auto d = makeConstantStorePathRef(inputDrv);
373373
for (const auto & [outputName, childNode] : inputNode.childMap) {
374374
SingleDerivedPath next = SingleDerivedPath::Built{d, outputName};
375-
accumRealisations(
375+
self(
376376
// TODO deep resolutions for dynamic derivations, issue #8947, would go here.
377377
resolveDerivedPath(store, next, evalStore_),
378378
childNode);

src/libstore/nar-accessor.cc

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,7 @@ struct NarAccessor : public SourceAccessor
144144
NarAccessor(const nlohmann::json & listing, GetNarBytes getNarBytes)
145145
: getNarBytes(getNarBytes)
146146
{
147-
using json = nlohmann::json;
148-
149-
std::function<void(NarMember &, const json &)> recurse;
150-
151-
recurse = [&](NarMember & member, const json & v) {
147+
[&](this const auto & recurse, NarMember & member, const nlohmann::json & v) -> void {
152148
std::string type = v["type"];
153149

154150
if (type == "directory") {
@@ -167,9 +163,7 @@ struct NarAccessor : public SourceAccessor
167163
member.target = v.value("target", "");
168164
} else
169165
return;
170-
};
171-
172-
recurse(root, listing);
166+
}(root, listing);
173167
}
174168

175169
NarMember * find(const CanonPath & path)

src/libutil/archive.cc

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ void SourceAccessor::dumpPath(const CanonPath & path, Sink & sink, PathFilter &
4747
writePadding(*size, sink);
4848
};
4949

50-
std::function<void(const CanonPath & path)> dump;
50+
sink << narVersionMagic1;
5151

52-
dump = [&](const CanonPath & path) {
52+
[&, &this_(*this)](this const auto & dump, const CanonPath & path) -> void {
5353
checkInterrupt();
5454

55-
auto st = lstat(path);
55+
auto st = this_.lstat(path);
5656

5757
sink << "(";
5858

@@ -69,7 +69,7 @@ void SourceAccessor::dumpPath(const CanonPath & path, Sink & sink, PathFilter &
6969
/* If we're on a case-insensitive system like macOS, undo
7070
the case hack applied by restorePath(). */
7171
StringMap unhacked;
72-
for (auto & i : readDirectory(path))
72+
for (auto & i : this_.readDirectory(path))
7373
if (archiveSettings.useCaseHack) {
7474
std::string name(i.first);
7575
size_t pos = i.first.find(caseHackSuffix);
@@ -92,16 +92,13 @@ void SourceAccessor::dumpPath(const CanonPath & path, Sink & sink, PathFilter &
9292
}
9393

9494
else if (st.type == tSymlink)
95-
sink << "type" << "symlink" << "target" << readLink(path);
95+
sink << "type" << "symlink" << "target" << this_.readLink(path);
9696

9797
else
9898
throw Error("file '%s' has an unsupported type", path);
9999

100100
sink << ")";
101-
};
102-
103-
sink << narVersionMagic1;
104-
dump(path);
101+
}(path);
105102
}
106103

107104
time_t dumpPathAndGetMtime(const Path & path, Sink & sink, PathFilter & filter)

src/libutil/include/nix/util/closure.hh

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,9 @@ void computeClosure(const set<T> startElts, set<T> & res, GetEdgesAsync<T> getEd
2424

2525
Sync<State> state_(State{0, res, 0});
2626

27-
std::function<void(const T &)> enqueue;
28-
2927
std::condition_variable done;
3028

31-
enqueue = [&](const T & current) -> void {
29+
auto enqueue = [&](this auto & enqueue, const T & current) -> void {
3230
{
3331
auto state(state_.lock());
3432
if (state->exc)

0 commit comments

Comments
 (0)