From 1a14dc6e44ee905e5e404c6360980be8c70f3884 Mon Sep 17 00:00:00 2001 From: sternenseemann Date: Tue, 16 Sep 2025 15:51:50 +0200 Subject: [PATCH] haskellPackages.callPackage: preserve functionArgs Our wrapper for lib.makeOverridable wraps the underlying function which means the wrapper function doesn't replicate the same set pattern. We can, however, tell lib.functionArgs about the permissible arguments by making the function a functor and adding __functionArgs. --- .../haskell-modules/make-package-set.nix | 42 +++++++++++-------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/pkgs/development/haskell-modules/make-package-set.nix b/pkgs/development/haskell-modules/make-package-set.nix index 320b331fc25d..1ee7af6657d1 100644 --- a/pkgs/development/haskell-modules/make-package-set.nix +++ b/pkgs/development/haskell-modules/make-package-set.nix @@ -107,29 +107,35 @@ let # is that nix has no way to "passthrough" args while preserving the reflection # info that callPackage uses to determine the arguments). drv = if lib.isFunction fn then fn else import fn; - auto = builtins.intersectAttrs (lib.functionArgs drv) scope; + drvFunctionArgs = lib.functionArgs drv; + auto = builtins.intersectAttrs drvFunctionArgs scope; # Converts a returned function to a functor attribute set if necessary ensureAttrs = v: if builtins.isFunction v then { __functor = _: v; } else v; # this wraps the `drv` function to add `scope` and `overrideScope` to the result. - drvScope = - allArgs: - ensureAttrs (drv allArgs) - // { - inherit scope; - overrideScope = - f: - let - newScope = mkScope (fix' (extends f scope.__unfix__)); - in - # note that we have to be careful here: `allArgs` includes the auto-arguments that - # weren't manually specified. If we would just pass `allArgs` to the recursive call here, - # then we wouldn't look up any packages in the scope in the next interation, because it - # appears as if all arguments were already manually passed, so the scope change would do - # nothing. - callPackageWithScope newScope drv manualArgs; - }; + # it's a functor, so that we can pass through `functionArgs` + drvScope = { + __functor = + _: allArgs: + ensureAttrs (drv allArgs) + // { + inherit scope; + overrideScope = + f: + let + newScope = mkScope (fix' (extends f scope.__unfix__)); + in + # note that we have to be careful here: `allArgs` includes the auto-arguments that + # weren't manually specified. If we would just pass `allArgs` to the recursive call here, + # then we wouldn't look up any packages in the scope in the next interation, because it + # appears as if all arguments were already manually passed, so the scope change would do + # nothing. + callPackageWithScope newScope drv manualArgs; + }; + # `drvScope` accepts the same arguments as `drv` + __functionArgs = drvFunctionArgs; + }; in lib.makeOverridable drvScope (auto // manualArgs);