Loading lib/default.nix +2 −1 Original line number Diff line number Diff line Loading @@ -79,7 +79,8 @@ let fromHexString toHexString toBaseDigits inPureEvalMode isBool isInt pathExists genericClosure readFile; inherit (self.fixedPoints) fix fix' converge extends composeExtensions composeManyExtensions makeExtensible makeExtensibleWithCustomName; composeManyExtensions makeExtensible makeExtensibleWithCustomName toExtension; inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath getAttrFromPath attrVals attrNames attrValues getAttrs catAttrs filterAttrs filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs Loading lib/fixed-points.nix +72 −0 Original line number Diff line number Diff line Loading @@ -438,4 +438,76 @@ rec { ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs); } ); /** Convert to an extending function (overlay). `toExtension` is the `toFunction` for extending functions (a.k.a. extensions or overlays). It converts a non-function or a single-argument function to an extending function, while returning a two-argument function as-is. That is, it takes a value of the shape `x`, `prev: x`, or `final: prev: x`, and returns `final: prev: x`, assuming `x` is not a function. This function takes care of the input to `stdenv.mkDerivation`'s `overrideAttrs` function. It bridges the gap between `<pkg>.overrideAttrs` before and after the overlay-style support. # Inputs `f` : The function or value to convert to an extending function. # Type ``` toExtension :: b' -> Any -> Any -> b' or toExtension :: (a -> b') -> Any -> a -> b' or toExtension :: (a -> a -> b) -> a -> a -> b where b' = ! Callable Set a = b = b' = AttrSet & ! Callable to make toExtension return an extending function. ``` # Examples :::{.example} ## `lib.fixedPoints.toExtension` usage example ```nix fix (final: { a = 0; c = final.a; }) => { a = 0; c = 0; }; fix (extends (toExtension { a = 1; b = 2; }) (final: { a = 0; c = final.a; })) => { a = 1; b = 2; c = 1; }; fix (extends (toExtension (prev: { a = 1; b = prev.a; })) (final: { a = 0; c = final.a; })) => { a = 1; b = 0; c = 1; }; fix (extends (toExtension (final: prev: { a = 1; b = prev.a; c = final.a + 1 })) (final: { a = 0; c = final.a; })) => { a = 1; b = 0; c = 2; }; ``` ::: */ toExtension = f: if lib.isFunction f then final: prev: let fPrev = f prev; in if lib.isFunction fPrev then # f is (final: prev: { ... }) f final prev else # f is (prev: { ... }) fPrev else # f is not a function; probably { ... } final: prev: f; } lib/tests/misc.nix +24 −5 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ let const escapeXML evalModules extends filter fix fold Loading Loading @@ -102,6 +103,7 @@ let take testAllTrue toBaseDigits toExtension toHexString fromHexString toInt Loading Loading @@ -233,11 +235,6 @@ runTests { ]; }; testFix = { expr = fix (x: {a = if x ? a then "a" else "b";}); expected = {a = "a";}; }; testComposeExtensions = { expr = let obj = makeExtensible (self: { foo = self.bar; }); f = self: super: { bar = false; baz = true; }; Loading Loading @@ -1237,6 +1234,28 @@ runTests { attrsToList { someFunc= a: a + 1;} ); # FIXED-POINTS testFix = { expr = fix (x: {a = if x ? a then "a" else "b";}); expected = {a = "a";}; }; testToExtension = { expr = [ (fix (final: { a = 0; c = final.a; })) (fix (extends (toExtension { a = 1; b = 2; }) (final: { a = 0; c = final.a; }))) (fix (extends (toExtension (prev: { a = 1; b = prev.a; })) (final: { a = 0; c = final.a; }))) (fix (extends (toExtension (final: prev: { a = 1; b = prev.a; c = final.a + 1; })) (final: { a = 0; c = final.a; }))) ]; expected = [ { a = 0; c = 0; } { a = 1; b = 2; c = 1; } { a = 1; b = 0; c = 1; } { a = 1; b = 0; c = 2; } ]; }; # GENERATORS # these tests assume attributes are converted to lists # in alphabetical order Loading pkgs/build-support/go/module.nix +1 −15 Original line number Diff line number Diff line Loading @@ -63,20 +63,6 @@ let GO111MODULE = "on"; GOTOOLCHAIN = "local"; toExtension = overlay0: if lib.isFunction overlay0 then final: prev: if lib.isFunction (overlay0 prev) then # `overlay0` is `final: prev: { ... }` overlay0 final prev else # `overlay0` is `prev: { ... }` overlay0 prev else # `overlay0` is `{ ... }` final: prev: overlay0; in (stdenv.mkDerivation (finalAttrs: args Loading Loading @@ -333,7 +319,7 @@ in # Canonicallize `overrideModAttrs` as an attribute overlay. # `passthru.overrideModAttrs` will be overridden # when users want to override `goModules`. overrideModAttrs = toExtension overrideModAttrs; overrideModAttrs = lib.toExtension overrideModAttrs; } // passthru; meta = { Loading pkgs/stdenv/generic/make-derivation.nix +2 −20 Original line number Diff line number Diff line Loading @@ -67,26 +67,8 @@ let # ^^^^ overrideAttrs = f0: let f = self: super: # Convert f0 to an overlay. Legacy is: # overrideAttrs (super: {}) # We want to introduce self. We follow the convention of overlays: # overrideAttrs (self: super: {}) # Which means the first parameter can be either self or super. # This is surprising, but far better than the confusion that would # arise from flipping an overlay's parameters in some cases. let x = f0 super; in if builtins.isFunction x then # Can't reuse `x`, because `self` comes first. # Looks inefficient, but `f0 super` was a cheap thunk. f0 self super else x; in makeDerivationExtensible (self: let super = rattrs self; in super // (if builtins.isFunction f0 || f0?__functor then f self super else f0)); (lib.extends (lib.toExtension f0) rattrs); finalPackage = mkDerivationSimple overrideAttrs args; Loading Loading
lib/default.nix +2 −1 Original line number Diff line number Diff line Loading @@ -79,7 +79,8 @@ let fromHexString toHexString toBaseDigits inPureEvalMode isBool isInt pathExists genericClosure readFile; inherit (self.fixedPoints) fix fix' converge extends composeExtensions composeManyExtensions makeExtensible makeExtensibleWithCustomName; composeManyExtensions makeExtensible makeExtensibleWithCustomName toExtension; inherit (self.attrsets) attrByPath hasAttrByPath setAttrByPath getAttrFromPath attrVals attrNames attrValues getAttrs catAttrs filterAttrs filterAttrsRecursive foldlAttrs foldAttrs collect nameValuePair mapAttrs Loading
lib/fixed-points.nix +72 −0 Original line number Diff line number Diff line Loading @@ -438,4 +438,76 @@ rec { ${extenderName} = f: makeExtensibleWithCustomName extenderName (extends f rattrs); } ); /** Convert to an extending function (overlay). `toExtension` is the `toFunction` for extending functions (a.k.a. extensions or overlays). It converts a non-function or a single-argument function to an extending function, while returning a two-argument function as-is. That is, it takes a value of the shape `x`, `prev: x`, or `final: prev: x`, and returns `final: prev: x`, assuming `x` is not a function. This function takes care of the input to `stdenv.mkDerivation`'s `overrideAttrs` function. It bridges the gap between `<pkg>.overrideAttrs` before and after the overlay-style support. # Inputs `f` : The function or value to convert to an extending function. # Type ``` toExtension :: b' -> Any -> Any -> b' or toExtension :: (a -> b') -> Any -> a -> b' or toExtension :: (a -> a -> b) -> a -> a -> b where b' = ! Callable Set a = b = b' = AttrSet & ! Callable to make toExtension return an extending function. ``` # Examples :::{.example} ## `lib.fixedPoints.toExtension` usage example ```nix fix (final: { a = 0; c = final.a; }) => { a = 0; c = 0; }; fix (extends (toExtension { a = 1; b = 2; }) (final: { a = 0; c = final.a; })) => { a = 1; b = 2; c = 1; }; fix (extends (toExtension (prev: { a = 1; b = prev.a; })) (final: { a = 0; c = final.a; })) => { a = 1; b = 0; c = 1; }; fix (extends (toExtension (final: prev: { a = 1; b = prev.a; c = final.a + 1 })) (final: { a = 0; c = final.a; })) => { a = 1; b = 0; c = 2; }; ``` ::: */ toExtension = f: if lib.isFunction f then final: prev: let fPrev = f prev; in if lib.isFunction fPrev then # f is (final: prev: { ... }) f final prev else # f is (prev: { ... }) fPrev else # f is not a function; probably { ... } final: prev: f; }
lib/tests/misc.nix +24 −5 Original line number Diff line number Diff line Loading @@ -45,6 +45,7 @@ let const escapeXML evalModules extends filter fix fold Loading Loading @@ -102,6 +103,7 @@ let take testAllTrue toBaseDigits toExtension toHexString fromHexString toInt Loading Loading @@ -233,11 +235,6 @@ runTests { ]; }; testFix = { expr = fix (x: {a = if x ? a then "a" else "b";}); expected = {a = "a";}; }; testComposeExtensions = { expr = let obj = makeExtensible (self: { foo = self.bar; }); f = self: super: { bar = false; baz = true; }; Loading Loading @@ -1237,6 +1234,28 @@ runTests { attrsToList { someFunc= a: a + 1;} ); # FIXED-POINTS testFix = { expr = fix (x: {a = if x ? a then "a" else "b";}); expected = {a = "a";}; }; testToExtension = { expr = [ (fix (final: { a = 0; c = final.a; })) (fix (extends (toExtension { a = 1; b = 2; }) (final: { a = 0; c = final.a; }))) (fix (extends (toExtension (prev: { a = 1; b = prev.a; })) (final: { a = 0; c = final.a; }))) (fix (extends (toExtension (final: prev: { a = 1; b = prev.a; c = final.a + 1; })) (final: { a = 0; c = final.a; }))) ]; expected = [ { a = 0; c = 0; } { a = 1; b = 2; c = 1; } { a = 1; b = 0; c = 1; } { a = 1; b = 0; c = 2; } ]; }; # GENERATORS # these tests assume attributes are converted to lists # in alphabetical order Loading
pkgs/build-support/go/module.nix +1 −15 Original line number Diff line number Diff line Loading @@ -63,20 +63,6 @@ let GO111MODULE = "on"; GOTOOLCHAIN = "local"; toExtension = overlay0: if lib.isFunction overlay0 then final: prev: if lib.isFunction (overlay0 prev) then # `overlay0` is `final: prev: { ... }` overlay0 final prev else # `overlay0` is `prev: { ... }` overlay0 prev else # `overlay0` is `{ ... }` final: prev: overlay0; in (stdenv.mkDerivation (finalAttrs: args Loading Loading @@ -333,7 +319,7 @@ in # Canonicallize `overrideModAttrs` as an attribute overlay. # `passthru.overrideModAttrs` will be overridden # when users want to override `goModules`. overrideModAttrs = toExtension overrideModAttrs; overrideModAttrs = lib.toExtension overrideModAttrs; } // passthru; meta = { Loading
pkgs/stdenv/generic/make-derivation.nix +2 −20 Original line number Diff line number Diff line Loading @@ -67,26 +67,8 @@ let # ^^^^ overrideAttrs = f0: let f = self: super: # Convert f0 to an overlay. Legacy is: # overrideAttrs (super: {}) # We want to introduce self. We follow the convention of overlays: # overrideAttrs (self: super: {}) # Which means the first parameter can be either self or super. # This is surprising, but far better than the confusion that would # arise from flipping an overlay's parameters in some cases. let x = f0 super; in if builtins.isFunction x then # Can't reuse `x`, because `self` comes first. # Looks inefficient, but `f0 super` was a cheap thunk. f0 self super else x; in makeDerivationExtensible (self: let super = rattrs self; in super // (if builtins.isFunction f0 || f0?__functor then f self super else f0)); (lib.extends (lib.toExtension f0) rattrs); finalPackage = mkDerivationSimple overrideAttrs args; Loading