summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/stdenv/meta.chapter.md2
-rw-r--r--doc/stdenv/stdenv.chapter.md15
-rw-r--r--pkgs/applications/misc/hello/default.nix2
-rw-r--r--pkgs/stdenv/generic/make-derivation.nix78
4 files changed, 49 insertions, 48 deletions
diff --git a/doc/stdenv/meta.chapter.md b/doc/stdenv/meta.chapter.md
index 64924dceb717f..e57669e261b31 100644
--- a/doc/stdenv/meta.chapter.md
+++ b/doc/stdenv/meta.chapter.md
@@ -187,7 +187,7 @@ all places.
 { stdenv, callPackage }:
 stdenv.mkDerivation (self: {
   # ...
-  passthru.tests.example = callPackage ./example.nix { my-package = self; };
+  passthru.tests.example = callPackage ./example.nix { my-package = self.public; }
 })
 ```
 
diff --git a/doc/stdenv/stdenv.chapter.md b/doc/stdenv/stdenv.chapter.md
index 2994f7020b198..b54d68cb5ddd0 100644
--- a/doc/stdenv/stdenv.chapter.md
+++ b/doc/stdenv/stdenv.chapter.md
@@ -319,7 +319,7 @@ For information about how to run the updates, execute `nix-shell maintainers/scr
 
 ### Recursive attributes in `mkDerivation`
 
-If you pass a function to `mkDerivation`, it will receive as its argument the final output of the same `mkDerivation` call. For example:
+If you pass a function to `mkDerivation`, it will receive as its argument the final arguments, considering use of `overrideAttrs`. For example:
 
 ```nix
 mkDerivation (self: {
@@ -331,9 +331,14 @@ mkDerivation (self: {
 ```
 
 Note that this does not use the `rec` keyword to reuse `withFeature` in `configureFlags`.
+The `rec` keyword works at the syntax level and is unaware of overriding.
+
 Instead, the definition references `self`, allowing users to change `withFeature`
 consistently with `overrideAttrs`.
 
+`self` also contains the attribute `public`, which represents the final package,
+including the output paths, etc.
+
 Let's look at a more elaborate example to understand the differences between
 various bindings:
 
@@ -347,11 +352,11 @@ let pkg =
     packages = [];
 
     # `passthru.tests` is a commonly defined attribute.
-    passthru.tests.simple = f self;
+    passthru.tests.simple = f self.public;
 
     # An example of an attribute containing a function
     passthru.appendPackages = packages':
-      self.overrideAttrs (newSelf: super: {
+      self.public.overrideAttrs (newSelf: super: {
         packages = super.packages ++ packages';
       });
 
@@ -363,9 +368,7 @@ let pkg =
 in pkg
 ```
 
-Unlike the `pkg` binding in the above example, the `self` parameter always references the final package. For instance `(pkg.overrideAttrs(x)).self` is identical to `pkg.overrideAttrs(x)`, whereas `(pkg.overrideAttrs(x)).original` is the same as `pkg`.
-
-This is also different from `mkDerivation rec { ..... }`, which binds the recursive references immediately, so it allows you to reference original _inputs_ only.
+Unlike the `pkg` binding in the above example, the `self` parameter always references the final attributes. For instance `(pkg.overrideAttrs(x)).self.public` is identical to `pkg.overrideAttrs(x)`, whereas `(pkg.overrideAttrs(x)).original` is the same as `pkg`.
 
 See also the section about [`passthru.tests`](#var-meta-tests).
 
diff --git a/pkgs/applications/misc/hello/default.nix b/pkgs/applications/misc/hello/default.nix
index 0ea6570b32087..75887348730f1 100644
--- a/pkgs/applications/misc/hello/default.nix
+++ b/pkgs/applications/misc/hello/default.nix
@@ -28,7 +28,7 @@ stdenv.mkDerivation (self: {
         (nixos { environment.noXlibs = true; }).pkgs.hello;
   };
 
-  passthru.tests.run = callPackage ./test.nix { hello = self; };
+  passthru.tests.run = callPackage ./test.nix { hello = self.public; };
 
   meta = with lib; {
     description = "A program that produces a familiar, friendly greeting";
diff --git a/pkgs/stdenv/generic/make-derivation.nix b/pkgs/stdenv/generic/make-derivation.nix
index 2a47ea993839a..ac661d9429ff9 100644
--- a/pkgs/stdenv/generic/make-derivation.nix
+++ b/pkgs/stdenv/generic/make-derivation.nix
@@ -17,52 +17,50 @@ let
       else makeDerivationExtensibleConst mkDerivationSimple fnOrAttrs;
 
   # Based off lib.makeExtensible, with modifications:
-  #  - lib.fix' -> lib.fix ∘ mkDerivationSimple; then inline fix
-  #  - convert `f` to an overlay
-  #  - inline overrideAttrs and make it positional instead of // to reduce allocs
   makeDerivationExtensible = mkDerivationSimple: rattrs:
     let
-      r = mkDerivationSimple
-        (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 mkDerivationSimple
-              (self: let super = rattrs self; in super // f self super))
-        (rattrs r);
-    in r;
+      args = rattrs (args // { inherit public; });
+      public =
+        mkDerivationSimple
+          (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 mkDerivationSimple
+                (self: let super = rattrs self; in super // f self super))
+          args;
+    in public;
 
   # makeDerivationExtensibleConst == makeDerivationExtensible (_: attrs),
   # but pre-evaluated for a slight improvement in performance.
   makeDerivationExtensibleConst = mkDerivationSimple: attrs:
-    mkDerivationSimple (f0:
-      let
-        f = self: super:
-          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 mkDerivationSimple (self: attrs // f self attrs))
+    mkDerivationSimple
+      (f0:
+        let
+          f = self: super:
+            let x = f0 super;
+            in
+              if builtins.isFunction x
+              then
+                f0 self super
+              else x;
+        in
+          makeDerivationExtensible mkDerivationSimple (self: attrs // f self attrs))
       attrs;
 
 in