diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index bef3a4923a49..0ac59c3e461b 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -57,6 +57,7 @@ let foldlAttrs foldr functionArgs + genAttrs generators genList getExe @@ -930,6 +931,54 @@ runTests { expected = "1.2.3"; }; + testFunctionArgsNestedFunctors = + let + faOrig = { + x = false; + }; + faAlt = { + x = false; + y = true; + }; + f0 = { x, ... }: x; + in + { + expr = { + a = functionArgs { + __functor = self: { + __functor = self: f0; + __functionArgs = faAlt; + }; + }; + b = functionArgs { __functor = self: { __functor = self: f0; }; }; + c = functionArgs { + __functor = { + __functor = self: outer: f0; + }; + }; + d = functionArgs { + __functor = { + __functor = self: outer: { + __functor = self: f0; + __functionArgs = faAlt; + }; + }; + }; + e = functionArgs { + __functor = { + __functor = self: outer: { __functor = self: f0; }; + }; + }; + }; + expected = { + a = faAlt; + b = faOrig; + c = faOrig; + d = faAlt; + e = faOrig; + }; + }; + testIsFunctionStr = { expr = isFunction "a"; expected = false; diff --git a/lib/trivial.nix b/lib/trivial.nix index ffe8eab1b28b..7dd908a7efcd 100644 --- a/lib/trivial.nix +++ b/lib/trivial.nix @@ -1104,9 +1104,22 @@ in */ functionArgs = let - functionArgs = builtins.functionArgs; + functionArgsLambda = builtins.functionArgs; in - f: if f ? __functor then f.__functionArgs or (functionArgs (f.__functor f)) else functionArgs f; + f: + if f ? __functor then + f.__functionArgs or ( + let + fInner = f.__functor f; + in + # Peel one recursion to avoid calling functionArgs + if fInner ? __functor then + fInner.__functionArgs or (functionArgs fInner) + else + functionArgsLambda fInner + ) + else + functionArgsLambda f; /** Check whether something is a function or something