about summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorSilvan Mosberger <contact@infinisil.com>2023-11-14 05:33:40 +0100
committerGitHub <noreply@github.com>2023-11-14 05:33:40 +0100
commit7eddbf56907e20b14a2996597cfc6619d1c18aed (patch)
tree96ee3e93207493cbdd2b15d5c871ab85977137b7 /lib
parent5d6c73222280b7f69109dfa5c9572f4b74c3453c (diff)
parentb3e2c150007b6d54f09a1b209fe66f6d0a1e70a7 (diff)
Merge pull request #265710 from ShamrockLee/lib-copy-function-args
lib.mirrorFunctionArgs: init
Diffstat (limited to 'lib')
-rw-r--r--lib/customisation.nix18
-rw-r--r--lib/default.nix2
-rw-r--r--lib/trivial.nix34
3 files changed, 45 insertions, 9 deletions
diff --git a/lib/customisation.nix b/lib/customisation.nix
index c7d40339d05f5..08fc5db0614de 100644
--- a/lib/customisation.nix
+++ b/lib/customisation.nix
@@ -76,19 +76,22 @@ rec {
      Type:
        makeOverridable :: (AttrSet -> a) -> AttrSet -> a
   */
-  makeOverridable = f: lib.setFunctionArgs
-    (origArgs: let
+  makeOverridable = f:
+    let
+      # Creates a functor with the same arguments as f
+      mirrorArgs = lib.mirrorFunctionArgs f;
+    in
+    mirrorArgs (origArgs:
+    let
       result = f origArgs;
 
-      # Creates a functor with the same arguments as f
-      copyArgs = g: lib.setFunctionArgs g (lib.functionArgs f);
       # Changes the original arguments with (potentially a function that returns) a set of new attributes
       overrideWith = newArgs: origArgs // (if lib.isFunction newArgs then newArgs origArgs else newArgs);
 
       # Re-call the function but with different arguments
-      overrideArgs = copyArgs (newArgs: makeOverridable f (overrideWith newArgs));
+      overrideArgs = mirrorArgs (newArgs: makeOverridable f (overrideWith newArgs));
       # Change the result of the function call by applying g to it
-      overrideResult = g: makeOverridable (copyArgs (args: g (f args))) origArgs;
+      overrideResult = g: makeOverridable (mirrorArgs (args: g (f args))) origArgs;
     in
       if builtins.isAttrs result then
         result // {
@@ -102,8 +105,7 @@ rec {
         lib.setFunctionArgs result (lib.functionArgs result) // {
           override = overrideArgs;
         }
-      else result)
-    (lib.functionArgs f);
+      else result);
 
 
   /* Call the package function in the file `fn` with the required
diff --git a/lib/default.nix b/lib/default.nix
index fe737a125e680..0dac50a08caa0 100644
--- a/lib/default.nix
+++ b/lib/default.nix
@@ -74,7 +74,7 @@ let
       importJSON importTOML warn warnIf warnIfNot throwIf throwIfNot checkListOfEnum
       info showWarnings nixpkgsVersion version isInOldestRelease
       mod compare splitByAndCompare
-      functionArgs setFunctionArgs isFunction toFunction
+      functionArgs setFunctionArgs isFunction toFunction mirrorFunctionArgs
       toHexString toBaseDigits inPureEvalMode;
     inherit (self.fixedPoints) fix fix' converge extends composeExtensions
       composeManyExtensions makeExtensible makeExtensibleWithCustomName;
diff --git a/lib/trivial.nix b/lib/trivial.nix
index c23fc6070be46..a89c1aa25b1f7 100644
--- a/lib/trivial.nix
+++ b/lib/trivial.nix
@@ -449,6 +449,40 @@ rec {
     (f ? __functor && isFunction (f.__functor f));
 
   /*
+    `mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`)
+    but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`).
+
+    Type:
+      mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
+
+    Example:
+      addab = {a, b}: a + b
+      addab { a = 2; b = 4; }
+      => 6
+      lib.functionArgs addab
+      => { a = false; b = false; }
+      addab1 = attrs: addab attrs + 1
+      addab1 { a = 2; b = 4; }
+      => 7
+      lib.functionArgs addab1
+      => { }
+      addab1' = lib.mirrorFunctionArgs addab addab1
+      addab1' { a = 2; b = 4; }
+      => 7
+      lib.functionArgs addab1'
+      => { a = false; b = false; }
+  */
+  mirrorFunctionArgs =
+    # Function to provide the argument metadata
+    f:
+    let
+      fArgs = functionArgs f;
+    in
+    # Function to set the argument metadata to
+    g:
+    setFunctionArgs g fArgs;
+
+  /*
     Turns any non-callable values into constant functions.
     Returns callable values as is.