about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lib/generators.nix12
-rw-r--r--lib/tests/misc.nix15
2 files changed, 26 insertions, 1 deletions
diff --git a/lib/generators.nix b/lib/generators.nix
index 3bc0fee332aea..431b93c4ebbc6 100644
--- a/lib/generators.nix
+++ b/lib/generators.nix
@@ -251,6 +251,16 @@ rec {
     }:
       assert builtins.isInt depthLimit;
       let
+        specialAttrs = [
+          "__functor"
+          "__functionArgs"
+          "__toString"
+          "__pretty"
+        ];
+        stepIntoAttr = evalNext: name:
+          if builtins.elem name specialAttrs
+            then id
+            else evalNext;
         transform = depth:
           if depthLimit != null && depth > depthLimit then
             if throwOnDepthLimit
@@ -261,7 +271,7 @@ rec {
           let
             evalNext = x: mapAny (depth + 1) (transform (depth + 1) x);
           in
-            if isAttrs v then mapAttrs (const evalNext) v
+            if isAttrs v then mapAttrs (stepIntoAttr evalNext) v
             else if isList v then map evalNext v
             else transform (depth + 1) v;
       in
diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix
index 1154edf1de628..584a946e92cc1 100644
--- a/lib/tests/misc.nix
+++ b/lib/tests/misc.nix
@@ -674,6 +674,21 @@ runTests {
       expected = false;
     };
 
+  testWithRecursionDealsWithFunctors =
+    let
+      functor = {
+        __functor = self: { a, b, }: null;
+      };
+      a = {
+        value = "1234";
+        b = functor;
+        c.d = functor;
+      };
+    in {
+      expr = generators.toPretty { } (generators.withRecursion { depthLimit = 1; throwOnDepthLimit = false; } a);
+      expected = "{\n  b = <function, args: {a, b}>;\n  c = {\n    d = \"<unevaluated>\";\n  };\n  value = \"<unevaluated>\";\n}";
+    };
+
   testToPrettyMultiline = {
     expr = mapAttrs (const (generators.toPretty { })) rec {
       list = [ 3 4 [ false ] ];