Skip to content

Have fun: std::function without null#15360

Merged
Ericson2314 merged 2 commits into
NixOS:masterfrom
roberth:fun
Feb 27, 2026
Merged

Have fun: std::function without null#15360
Ericson2314 merged 2 commits into
NixOS:masterfrom
roberth:fun

Conversation

@roberth
Copy link
Copy Markdown
Member

@roberth roberth commented Feb 27, 2026

Motivation

Tracking which functions may or may not be null is not my idea of fun.

This applies the same pattern we have with ref.

Side-catch:
1 line of dead code removed.
Occasional line reductions thanks to the shorter name, and a couple direct initializations. net: -9

Context

I've kept the puns to a minimum.

See commit messages for details.


Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@github-actions github-actions Bot added new-cli Relating to the "nix" command with-tests Issues related to testing. PRs with tests have some priority store Issues and pull requests concerning the Nix store repl The Read Eval Print Loop, "nix repl" command and debugger fetching Networking with the outside (non-Nix) world, input locking c api Nix as a C library with a stable interface labels Feb 27, 2026
Comment thread src/libutil/include/nix/util/fun.hh Outdated
Comment thread src/libexpr-c/nix_api_value.cc
Comment thread src/libutil-tests/fun.cc Outdated
Comment thread src/libutil-tests/fun.cc
Like `ref<T>` guarantees a non-null pointer, `fun<Sig>` guarantees a
non-null callable.

When a callable is nullable, use `std::function` directly — not
`optional<fun<>>`. The two types serve complementary roles:
`fun<Sig>` for non-null, `std::function<Sig>` for nullable.

Construction from callables (lambdas, function pointers) is implicit
since these are inherently non-null. Construction from `std::function`
is explicit, since it may be empty. `fun(nullptr)` is a deleted
overload.

A moved-from `fun<>` violates its non-null invariant, matching the
precedent set by `ref<T>`. Deleting moves was considered but deemed
unnecessary: the goal of this type is to document and enforce an
invariant, not to force non-null at all costs including performance.

`get_fn()` exposes the underlying `std::function` for API that only
exists there, such as `target<>()`.
- `fun` was used for variable/field names in a number of places.
  These have been replaced by similar or more descriptive names,
  to avoid name shadowing, which is not allowed in the GCC-based build.

- Use in-place construction instead of assignment.

- `FilteringSourceAccessor::checkAccess` had a fallback for when
  `makeNotAllowedError` was null. Since `MakeNotAllowedError` is now
  `fun<>`, we've proven the null branch is dead code and have removed it.

- `src/nix/flake.cc`, `src/nix/search.cc`, `src/nix/ls.cc` are left
  as-is — the self-referential lambdas there cause too much
  reindentation for too little benefit.
Copy link
Copy Markdown
Contributor

@xokdvium xokdvium left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A bit churny but oh well.

@Ericson2314 Ericson2314 added this pull request to the merge queue Feb 27, 2026
Merged via the queue into NixOS:master with commit 0acd056 Feb 27, 2026
15 checks passed
brittonr pushed a commit to brittonr/nix that referenced this pull request Apr 1, 2026
Have `fun`: `std::function` without null
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

c api Nix as a C library with a stable interface fetching Networking with the outside (non-Nix) world, input locking new-cli Relating to the "nix" command repl The Read Eval Print Loop, "nix repl" command and debugger store Issues and pull requests concerning the Nix store with-tests Issues related to testing. PRs with tests have some priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants