···251251 }:
252252 assert builtins.isInt depthLimit;
253253 let
254254+ specialAttrs = [
255255+ "__functor"
256256+ "__functionArgs"
257257+ "__toString"
258258+ "__pretty"
259259+ ];
260260+ stepIntoAttr = evalNext: name:
261261+ if builtins.elem name specialAttrs
262262+ then id
263263+ else evalNext;
254264 transform = depth:
255265 if depthLimit != null && depth > depthLimit then
256266 if throwOnDepthLimit
···261271 let
262272 evalNext = x: mapAny (depth + 1) (transform (depth + 1) x);
263273 in
264264- if isAttrs v then mapAttrs (const evalNext) v
274274+ if isAttrs v then mapAttrs (stepIntoAttr evalNext) v
265275 else if isList v then map evalNext v
266276 else transform (depth + 1) v;
267277 in
+15
lib/tests/misc.nix
···674674 expected = false;
675675 };
676676677677+ testWithRecursionDealsWithFunctors =
678678+ let
679679+ functor = {
680680+ __functor = self: { a, b, }: null;
681681+ };
682682+ a = {
683683+ value = "1234";
684684+ b = functor;
685685+ c.d = functor;
686686+ };
687687+ in {
688688+ expr = generators.toPretty { } (generators.withRecursion { depthLimit = 1; throwOnDepthLimit = false; } a);
689689+ expected = "{\n b = <function, args: {a, b}>;\n c = {\n d = \"<unevaluated>\";\n };\n value = \"<unevaluated>\";\n}";
690690+ };
691691+677692 testToPrettyMultiline = {
678693 expr = mapAttrs (const (generators.toPretty { })) rec {
679694 list = [ 3 4 [ false ] ];