summary refs log tree commit diff
path: root/lib
diff options
context:
space:
mode:
authorsternenseemann <0rpkxez4ksa01gb3typccl0i@systemli.org>2021-01-31 14:25:07 +0100
committersternenseemann <0rpkxez4ksa01gb3typccl0i@systemli.org>2021-01-31 15:35:17 +0100
commitd9a7d03da8c58aa863911506ae3153729f8931da (patch)
treec9d70c6696c1cea8fc04793f9e58f88814996262 /lib
parent552d7182874ef1b8fcf25c55d3777719a5ec7bfb (diff)
downloadnixpkgs-d9a7d03da8c58aa863911506ae3153729f8931da.tar
nixpkgs-d9a7d03da8c58aa863911506ae3153729f8931da.tar.gz
nixpkgs-d9a7d03da8c58aa863911506ae3153729f8931da.tar.bz2
nixpkgs-d9a7d03da8c58aa863911506ae3153729f8931da.tar.lz
nixpkgs-d9a7d03da8c58aa863911506ae3153729f8931da.tar.xz
nixpkgs-d9a7d03da8c58aa863911506ae3153729f8931da.tar.zst
nixpkgs-d9a7d03da8c58aa863911506ae3153729f8931da.zip
lib/generators: fix toPretty throwing on (partially applied) builtins
An high level example case of this problem occuring can be found below:

nix-repl> lib.generators.toPretty {} (lib.concatStringsSep "\n")
error: 'functionArgs' requires a function, at /home/lukas/src/nix/nixpkgs/lib/trivial.nix:334:42

However this does not happen on other partially applied functions:

nix-repl> lib.generators.toPretty {} (lib.concatMapStringsSep "\n")
"<function>"

The issue, as it turns out is that while builtins are functions,
builtins.functionArgs throws if is passed a builtin or a partially
applied builtin:

nix-repl> lib.generators.toPretty {} builtins.toString
error: 'functionArgs' requires a function, at /home/lukas/src/nix/nixpkgs/lib/trivial.nix:334:42

nix-repl> lib.generators.toPretty {} (builtins.foldl' (a: b: a + b))
error: 'functionArgs' requires a function, at /home/lukas/src/nix/nixpkgs/lib/trivial.nix:334:42

I'm pretty sure this qualifies as a nix bug and should be filed
accordingly, but we can work around it in lib.generators.toPretty by
using tryEval and falling back to {} which functionArgs _should_ return
for builtins.

The nix behavior is inconsistent to say the least:

nix-repl> builtins.functionArgs builtins.functionArgs
error: 'functionArgs' requires a function, at (string):1:1

nix-repl> builtins.typeOf builtins.functionArgs
"lambda"

builtins.functionArgs (a: 1 + a)
{ }

nix-repl> builtins.typeOf (a: 1 + a)
"lambda"
Diffstat (limited to 'lib')
-rw-r--r--lib/generators.nix13
1 files changed, 9 insertions, 4 deletions
diff --git a/lib/generators.nix b/lib/generators.nix
index 501a23599f4..9546f5b5b0a 100644
--- a/lib/generators.nix
+++ b/lib/generators.nix
@@ -236,12 +236,17 @@ rec {
         + libStr.concatMapStringsSep introSpace (go (indent + "  ")) v
         + outroSpace + "]"
     else if isFunction v then
-      let fna = lib.functionArgs v;
+      # functionArgs throws in case of (partially applied) builtins
+      # on nix before commit b2748c6e99239ff6803ba0da76c362790c8be192
+      # which includes current nix stable
+      # TODO remove tryEval workaround when the issue is resolved on nix stable
+      let fna = builtins.tryEval (lib.functionArgs v);
           showFnas = concatStringsSep ", " (libAttr.mapAttrsToList
                        (name: hasDefVal: if hasDefVal then name + "?" else name)
-                       fna);
-      in if fna == {}    then "<function>"
-                         else "<function, args: {${showFnas}}>"
+                       fna.value);
+      in if !fna.success || fna.value == {}
+         then "<function>"
+         else "<function, args: {${showFnas}}>"
     else if isAttrs    v then
       # apply pretty values if allowed
       if attrNames v == [ "__pretty" "val" ] && allowPrettyValues