From 72037880688ff9c6f4188a5746c3ab5ce7215628 Mon Sep 17 00:00:00 2001 From: Maximilian Bosch Date: Tue, 12 Apr 2022 12:26:25 +0200 Subject: lib/generators: withRecursion: don't break attr-sets with special attrs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #168327 The issue reported there can be demonstrated with the following expression: → nix-instantiate --eval -E "with import ./. {}; pkgs.lib.options.showDefs [ { file = \"foo\"; value = pkgs.rust.packages.stable.buildRustPackages; } ]" error: attempt to call something which is not a function but a string at /home/ma27/Projects/nixpkgs/lib/trivial.nix:442:35: 441| isFunction = f: builtins.isFunction f || 442| (f ? __functor && isFunction (f.__functor f)); | ^ 443| Basically, if a `__functor` is in an attribute-set at depth-limit, `__functor` will be set to `""`. This however breaks `lib.isFunction` which checks for a `__functor` by invoking `__functor` with `f` itself. The same issue - "magic" attributes being shadowed by `withRecursion` - also applies to others such as `__pretty`/`__functionArgs`/`__toString`. Since these attributes have a low-risk of causing a stack overflow (because these are flat attr-sets or even functions), ignoring them in `withRecursion` seems like a valid solution. --- lib/tests/misc.nix | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'lib/tests') diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index fcccf89cc888c..ccfa9cc5ec14f 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -613,6 +613,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 = ;\n c = {\n d = \"\";\n };\n value = \"\";\n}"; + }; + testToPrettyMultiline = { expr = mapAttrs (const (generators.toPretty { })) rec { list = [ 3 4 [ false ] ]; -- cgit 1.4.1