From 6cc2ef7c6d571a668f2e02fa7a485ab8119c8d4b Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Wed, 14 Jan 2026 17:20:25 +0100 Subject: [PATCH] libexpr: remove RegisterPrimOp static initializer helper Change-Id: I0cc6d54fca26c66b13f930303086b08b2afb4d54 --- doc/manual/rl-next/static-initializers.md | 11 +++++++++++ lix/libexpr/primops.cc | 11 ++++++----- lix/libexpr/primops.hh | 9 +++++++-- lix/libstore/settings/plugin-files.md | 2 +- tests/functional/plugins/plugintest.cc | 11 +++++------ 5 files changed, 30 insertions(+), 14 deletions(-) create mode 100644 doc/manual/rl-next/static-initializers.md diff --git a/doc/manual/rl-next/static-initializers.md b/doc/manual/rl-next/static-initializers.md new file mode 100644 index 000000000..79591d563 --- /dev/null +++ b/doc/manual/rl-next/static-initializers.md @@ -0,0 +1,11 @@ +--- +synopsis: "Plugin interfaces have changed (again)" +cls: [4933] +issues: [359] +category: "Miscellany" +credits: [horrors] +--- + +The `RegisterPrimOp` class used to register builtins has been removed. Plugins +must now call `PluginPrimOps::add` from their `nix_plugin_entry` with the same +parameters previously passed to `RegisterRrimOp` to register any new builtins. diff --git a/lix/libexpr/primops.cc b/lix/libexpr/primops.cc index 51d8106a7..aeafd683e 100644 --- a/lix/libexpr/primops.cc +++ b/lix/libexpr/primops.cc @@ -3038,10 +3038,9 @@ static void prim_splitVersion(EvalState & state, Value * * args, Value & v) * Primop registration *************************************************************/ +PluginPrimOps::PrimOps * PluginPrimOps::primOps; -RegisterPrimOp::PrimOps * RegisterPrimOp::primOps; - -RegisterPrimOp::RegisterPrimOp(PrimOpDetails && primOp) +void PluginPrimOps::add(PrimOpDetails && primOp) { if (!primOps) primOps = new PrimOps; primOps->emplace_back(std::move(primOp)); @@ -3083,14 +3082,16 @@ void EvalBuiltins::createBaseEnv(const SearchPath & searchPath, const Path & sto }); } - if (RegisterPrimOp::primOps) - for (auto & primOp : *RegisterPrimOp::primOps) + if (PluginPrimOps::primOps) { + for (auto & primOp : *PluginPrimOps::primOps) { if (experimentalFeatureSettings.isEnabled(primOp.experimentalFeature)) { auto primOpAdjusted = primOp; primOpAdjusted.arity = std::max(primOp.args.size(), primOp.arity); addPrimOp(std::move(primOpAdjusted)); } + } + } static PrimOp prim_initializeDerivation{{ .arity = 1, diff --git a/lix/libexpr/primops.hh b/lix/libexpr/primops.hh index 556ded156..dcc611f38 100644 --- a/lix/libexpr/primops.hh +++ b/lix/libexpr/primops.hh @@ -23,17 +23,22 @@ constexpr size_t nonRecursiveStackReservation = 128; */ constexpr size_t conservativeStackReservation = 16; -struct RegisterPrimOp +class PluginPrimOps { + friend EvalBuiltins; + typedef std::vector PrimOps; static PrimOps * primOps; +public: + PluginPrimOps() = delete; + /** * You can register a constant by passing an arity of 0. fun * will get called during EvalState initialization, so there * may be primops not yet added and builtins is not yet sorted. */ - RegisterPrimOp(PrimOpDetails && primOp); + static void add(PrimOpDetails && primOp); }; /* These primops are disabled without enableNativeCode, but plugins diff --git a/lix/libstore/settings/plugin-files.md b/lix/libstore/settings/plugin-files.md index 1bc00a0b9..ca8806498 100644 --- a/lix/libstore/settings/plugin-files.md +++ b/lix/libstore/settings/plugin-files.md @@ -14,7 +14,7 @@ If an entry in the list is a directory, all files in the directory are loaded as FIXME(jade): We should provide a `nix_plugin_finalize()` that gets called at some point in teardown for use cases like nix-otel which need to be able to cleanup, flush things to network, etc, on exit without having to do that from life-after-main(). In particular, these plugins may: -- Construct static instances of `RegisterPrimOp` to add new primops or constants to the expression language (FIXME: will be replaced with an explicit function). +- Add new primops or constants to the expression language by calling `PluginPrimOps::add`. - Add new store implementations with `StoreImplementations::add`. - Construct static instances of `GlobalConfig::Register` to add new config options. diff --git a/tests/functional/plugins/plugintest.cc b/tests/functional/plugins/plugintest.cc index e91dda774..bcaa8915a 100644 --- a/tests/functional/plugins/plugintest.cc +++ b/tests/functional/plugins/plugintest.cc @@ -36,13 +36,12 @@ static void prim_anotherNull (EvalState & state, Value ** args, Value & v) v.mkBool(false); } -static RegisterPrimOp rp({ - .name = "anotherNull", - .arity = 0, - .fun = prim_anotherNull, -}); - extern "C" void nix_plugin_entry() { + PluginPrimOps::add({ + .name = "anotherNull", + .arity = 0, + .fun = prim_anotherNull, + }); entryCalled = true; }