about summary refs log tree commit diff
path: root/nixpkgs/lib
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2024-03-24 11:04:41 +0100
committerAlyssa Ross <hi@alyssa.is>2024-03-24 11:04:41 +0100
commit5423cabbbf2b6dec5568f1ecabd288d5d9a642ec (patch)
treef316a6a921bfefd3a63bd4502c2eb50ff1644f67 /nixpkgs/lib
parent46a88117a05c3469af5d99433af140c3de8ca088 (diff)
parent8aa81f34981add12aecada6c702ddbbd0375ca36 (diff)
downloadnixlib-5423cabbbf2b6dec5568f1ecabd288d5d9a642ec.tar
nixlib-5423cabbbf2b6dec5568f1ecabd288d5d9a642ec.tar.gz
nixlib-5423cabbbf2b6dec5568f1ecabd288d5d9a642ec.tar.bz2
nixlib-5423cabbbf2b6dec5568f1ecabd288d5d9a642ec.tar.lz
nixlib-5423cabbbf2b6dec5568f1ecabd288d5d9a642ec.tar.xz
nixlib-5423cabbbf2b6dec5568f1ecabd288d5d9a642ec.tar.zst
nixlib-5423cabbbf2b6dec5568f1ecabd288d5d9a642ec.zip
Merge branch 'nixos-unstable-small' of https://github.com/NixOS/nixpkgs
Diffstat (limited to 'nixpkgs/lib')
-rw-r--r--nixpkgs/lib/attrsets.nix1866
-rw-r--r--nixpkgs/lib/customisation.nix133
-rw-r--r--nixpkgs/lib/deprecated.nix104
-rw-r--r--nixpkgs/lib/generators.nix209
-rw-r--r--nixpkgs/lib/kernel.nix4
-rw-r--r--nixpkgs/lib/licenses.nix20
-rw-r--r--nixpkgs/lib/lists.nix1704
-rw-r--r--nixpkgs/lib/systems/default.nix4
-rw-r--r--nixpkgs/lib/tests/misc.nix89
-rw-r--r--nixpkgs/lib/tests/modules/alias-with-priority-can-override.nix13
-rw-r--r--nixpkgs/lib/tests/modules/alias-with-priority.nix13
-rw-r--r--nixpkgs/lib/tests/modules/extendModules-168767-imports.nix9
-rw-r--r--nixpkgs/lib/trivial.nix941
13 files changed, 3865 insertions, 1244 deletions
diff --git a/nixpkgs/lib/attrsets.nix b/nixpkgs/lib/attrsets.nix
index 34054460ba76..de5968b95348 100644
--- a/nixpkgs/lib/attrsets.nix
+++ b/nixpkgs/lib/attrsets.nix
@@ -1,4 +1,6 @@
-/* Operations on attribute sets. */
+/**
+  Operations on attribute sets.
+*/
 { lib }:
 
 let
@@ -12,35 +14,57 @@ rec {
   inherit (builtins) attrNames listToAttrs hasAttr isAttrs getAttr removeAttrs;
 
 
-  /* Return an attribute from nested attribute sets.
+  /**
+    Return an attribute from nested attribute sets.
+
+    Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+
+    ```nix
+    (x.a.b or 6) == attrByPath ["a" "b"] 6 x
+    # and
+    (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
+    ```
+
 
-     Nix has an [attribute selection operator `. or`](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+    # Inputs
 
-     ```nix
-     (x.a.b or 6) == attrByPath ["a" "b"] 6 x
-     # and
-     (x.${f p}."example.com" or 6) == attrByPath [ (f p) "example.com" ] 6 x
-     ```
+    `attrPath`
 
-     Example:
-       x = { a = { b = 3; }; }
-       # ["a" "b"] is equivalent to x.a.b
-       # 6 is a default value to return if the path does not exist in attrset
-       attrByPath ["a" "b"] 6 x
-       => 3
-       attrByPath ["z" "z"] 6 x
-       => 6
+    : A list of strings representing the attribute path to return from `set`
 
-     Type:
-       attrByPath :: [String] -> Any -> AttrSet -> Any
+    `default`
+
+    : Default value if `attrPath` does not resolve to an existing value
+
+    `set`
+
+    : The nested attribute set to select values from
+
+    # Type
 
+    ```
+    attrByPath :: [String] -> Any -> AttrSet -> Any
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrByPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    # ["a" "b"] is equivalent to x.a.b
+    # 6 is a default value to return if the path does not exist in attrset
+    attrByPath ["a" "b"] 6 x
+    => 3
+    attrByPath ["z" "z"] 6 x
+    => 6
+    ```
+
+    :::
   */
   attrByPath =
-    # A list of strings representing the attribute path to return from `set`
     attrPath:
-    # Default value if `attrPath` does not resolve to an existing value
     default:
-    # The nested attribute set to select values from
     set:
     let
       lenAttrPath = length attrPath;
@@ -57,37 +81,57 @@ rec {
     in
       attrByPath' 0 set;
 
-  /* Return if an attribute from nested attribute set exists.
+  /**
+    Return if an attribute from nested attribute set exists.
+
+    Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
 
-     Nix has a [has attribute operator `?`](https://nixos.org/manual/nix/stable/language/operators#has-attribute), which is sufficient for such queries, as long as the number of attributes is static. For example:
+    ```nix
+    (x?a.b) == hasAttryByPath ["a" "b"] x
+    # and
+    (x?${f p}."example.com") == hasAttryByPath [ (f p) "example.com" ] x
+    ```
+
+    **Laws**:
+     1.  ```nix
+         hasAttrByPath [] x == true
+         ```
+
+
+    # Inputs
 
-     ```nix
-     (x?a.b) == hasAttryByPath ["a" "b"] x
-     # and
-     (x?${f p}."example.com") == hasAttryByPath [ (f p) "example.com" ] x
-     ```
+    `attrPath`
 
-     **Laws**:
-      1.  ```nix
-          hasAttrByPath [] x == true
-          ```
+    : A list of strings representing the attribute path to check from `set`
 
-     Example:
-       x = { a = { b = 3; }; }
-       hasAttrByPath ["a" "b"] x
-       => true
-       hasAttrByPath ["z" "z"] x
-       => false
-       hasAttrByPath [] (throw "no need")
-       => true
+    `e`
 
-    Type:
-      hasAttrByPath :: [String] -> AttrSet -> Bool
+    : The nested attribute set to check
+
+    # Type
+
+    ```
+    hasAttrByPath :: [String] -> AttrSet -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.hasAttrByPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    hasAttrByPath ["a" "b"] x
+    => true
+    hasAttrByPath ["z" "z"] x
+    => false
+    hasAttrByPath [] (throw "no need")
+    => true
+    ```
+
+    :::
   */
   hasAttrByPath =
-    # A list of strings representing the attribute path to check from `set`
     attrPath:
-    # The nested attribute set to check
     e:
     let
       lenAttrPath = length attrPath;
@@ -103,7 +147,7 @@ rec {
     in
       hasAttrByPath' 0 e;
 
-  /*
+  /**
     Return the longest prefix of an attribute path that refers to an existing attribute in a nesting of attribute sets.
 
     Can be used after [`mapAttrsRecursiveCond`](#function-library-lib.attrsets.mapAttrsRecursiveCond) to apply a condition,
@@ -120,24 +164,43 @@ rec {
         hasAttrByPath (attrsets.longestValidPathPrefix p x) x == true
         ```
 
-    Example:
-      x = { a = { b = 3; }; }
-      attrsets.longestValidPathPrefix ["a" "b" "c"] x
-      => ["a" "b"]
-      attrsets.longestValidPathPrefix ["a"] x
-      => ["a"]
-      attrsets.longestValidPathPrefix ["z" "z"] x
-      => []
-      attrsets.longestValidPathPrefix ["z" "z"] (throw "no need")
-      => []
-
-    Type:
-      attrsets.longestValidPathPrefix :: [String] -> Value -> [String]
+
+    # Inputs
+
+    `attrPath`
+
+    : A list of strings representing the longest possible path that may be returned.
+
+    `v`
+
+    : The nested attribute set to check.
+
+    # Type
+
+    ```
+    attrsets.longestValidPathPrefix :: [String] -> Value -> [String]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.longestValidPathPrefix` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    attrsets.longestValidPathPrefix ["a" "b" "c"] x
+    => ["a" "b"]
+    attrsets.longestValidPathPrefix ["a"] x
+    => ["a"]
+    attrsets.longestValidPathPrefix ["z" "z"] x
+    => []
+    attrsets.longestValidPathPrefix ["z" "z"] (throw "no need")
+    => []
+    ```
+
+    :::
   */
   longestValidPathPrefix =
-    # A list of strings representing the longest possible path that may be returned.
     attrPath:
-    # The nested attribute set to check.
     v:
     let
       lenAttrPath = length attrPath;
@@ -168,19 +231,39 @@ rec {
     in
       getPrefixForSetAtIndex v 0;
 
-  /* Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
+  /**
+    Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
+
 
-     Example:
-       setAttrByPath ["a" "b"] 3
-       => { a = { b = 3; }; }
+    # Inputs
 
-     Type:
-       setAttrByPath :: [String] -> Any -> AttrSet
+    `attrPath`
+
+    : A list of strings representing the attribute path to set
+
+    `value`
+
+    : The value to set at the location described by `attrPath`
+
+    # Type
+
+    ```
+    setAttrByPath :: [String] -> Any -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.setAttrByPath` usage example
+
+    ```nix
+    setAttrByPath ["a" "b"] 3
+    => { a = { b = 3; }; }
+    ```
+
+    :::
   */
   setAttrByPath =
-    # A list of strings representing the attribute path to set
     attrPath:
-    # The value to set at the location described by `attrPath`
     value:
     let
       len = length attrPath;
@@ -190,47 +273,89 @@ rec {
         else { ${elemAt attrPath n} = atDepth (n + 1); };
     in atDepth 0;
 
-  /* Like `attrByPath`, but without a default value. If it doesn't find the
-     path it will throw an error.
+  /**
+    Like `attrByPath`, but without a default value. If it doesn't find the
+    path it will throw an error.
 
-     Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
+    Nix has an [attribute selection operator](https://nixos.org/manual/nix/stable/language/operators#attribute-selection) which is sufficient for such queries, as long as the number of attributes is static. For example:
 
     ```nix
-     x.a.b == getAttrByPath ["a" "b"] x
-     # and
-     x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
-     ```
-
-     Example:
-       x = { a = { b = 3; }; }
-       getAttrFromPath ["a" "b"] x
-       => 3
-       getAttrFromPath ["z" "z"] x
-       => error: cannot find attribute `z.z'
-
-     Type:
-       getAttrFromPath :: [String] -> AttrSet -> Any
+    x.a.b == getAttrByPath ["a" "b"] x
+    # and
+    x.${f p}."example.com" == getAttrByPath [ (f p) "example.com" ] x
+    ```
+
+
+    # Inputs
+
+    `attrPath`
+
+    : A list of strings representing the attribute path to get from `set`
+
+    `set`
+
+    : The nested attribute set to find the value in.
+
+    # Type
+
+    ```
+    getAttrFromPath :: [String] -> AttrSet -> Any
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getAttrFromPath` usage example
+
+    ```nix
+    x = { a = { b = 3; }; }
+    getAttrFromPath ["a" "b"] x
+    => 3
+    getAttrFromPath ["z" "z"] x
+    => error: cannot find attribute `z.z'
+    ```
+
+    :::
   */
   getAttrFromPath =
-    # A list of strings representing the attribute path to get from `set`
     attrPath:
-    # The nested attribute set to find the value in.
     set:
     attrByPath attrPath (abort ("cannot find attribute `" + concatStringsSep "." attrPath + "'")) set;
 
-  /* Map each attribute in the given set and merge them into a new attribute set.
+  /**
+    Map each attribute in the given set and merge them into a new attribute set.
+
+
+    # Inputs
 
-     Type:
-       concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet
+    `f`
 
-     Example:
-       concatMapAttrs
-         (name: value: {
-           ${name} = value;
-           ${name + value} = value;
-         })
-         { x = "a"; y = "b"; }
-       => { x = "a"; xa = "a"; y = "b"; yb = "b"; }
+    : 1\. Function argument
+
+    `v`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    concatMapAttrs :: (String -> a -> AttrSet) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.concatMapAttrs` usage example
+
+    ```nix
+    concatMapAttrs
+      (name: value: {
+        ${name} = value;
+        ${name + value} = value;
+      })
+      { x = "a"; y = "b"; }
+    => { x = "a"; xa = "a"; y = "b"; yb = "b"; }
+    ```
+
+    :::
   */
   concatMapAttrs = f: v:
     foldl' mergeAttrs { }
@@ -239,49 +364,61 @@ rec {
       );
 
 
-  /* Update or set specific paths of an attribute set.
-
-     Takes a list of updates to apply and an attribute set to apply them to,
-     and returns the attribute set with the updates applied. Updates are
-     represented as `{ path = ...; update = ...; }` values, where `path` is a
-     list of strings representing the attribute path that should be updated,
-     and `update` is a function that takes the old value at that attribute path
-     as an argument and returns the new
-     value it should be.
-
-     Properties:
-
-     - Updates to deeper attribute paths are applied before updates to more
-       shallow attribute paths
-
-     - Multiple updates to the same attribute path are applied in the order
-       they appear in the update list
-
-     - If any but the last `path` element leads into a value that is not an
-       attribute set, an error is thrown
-
-     - If there is an update for an attribute path that doesn't exist,
-       accessing the argument in the update function causes an error, but
-       intermediate attribute sets are implicitly created as needed
-
-     Example:
-       updateManyAttrsByPath [
-         {
-           path = [ "a" "b" ];
-           update = old: { d = old.c; };
-         }
-         {
-           path = [ "a" "b" "c" ];
-           update = old: old + 1;
-         }
-         {
-           path = [ "x" "y" ];
-           update = old: "xy";
-         }
-       ] { a.b.c = 0; }
-       => { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
-
-    Type: updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet
+  /**
+    Update or set specific paths of an attribute set.
+
+    Takes a list of updates to apply and an attribute set to apply them to,
+    and returns the attribute set with the updates applied. Updates are
+    represented as `{ path = ...; update = ...; }` values, where `path` is a
+    list of strings representing the attribute path that should be updated,
+    and `update` is a function that takes the old value at that attribute path
+    as an argument and returns the new
+    value it should be.
+
+    Properties:
+
+    - Updates to deeper attribute paths are applied before updates to more
+      shallow attribute paths
+
+    - Multiple updates to the same attribute path are applied in the order
+      they appear in the update list
+
+    - If any but the last `path` element leads into a value that is not an
+      attribute set, an error is thrown
+
+    - If there is an update for an attribute path that doesn't exist,
+      accessing the argument in the update function causes an error, but
+      intermediate attribute sets are implicitly created as needed
+
+    # Type
+
+    ```
+    updateManyAttrsByPath :: [{ path :: [String]; update :: (Any -> Any); }] -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.updateManyAttrsByPath` usage example
+
+    ```nix
+    updateManyAttrsByPath [
+      {
+        path = [ "a" "b" ];
+        update = old: { d = old.c; };
+      }
+      {
+        path = [ "a" "b" "c" ];
+        update = old: old + 1;
+      }
+      {
+        path = [ "x" "y" ];
+        update = old: "xy";
+      }
+    ] { a.b.c = 0; }
+    => { a = { b = { d = 1; }; }; x = { y = "xy"; }; }
+    ```
+
+    :::
   */
   updateManyAttrsByPath = let
     # When recursing into attributes, instead of updating the `path` of each
@@ -342,96 +479,208 @@ rec {
 
   in updates: value: go 0 true value updates;
 
-  /* Return the specified attributes from a set.
+  /**
+    Return the specified attributes from a set.
+
+
+    # Inputs
+
+    `nameList`
+
+    : The list of attributes to fetch from `set`. Each attribute name must exist on the attrbitue set
 
-     Example:
-       attrVals ["a" "b" "c"] as
-       => [as.a as.b as.c]
+    `set`
 
-     Type:
-       attrVals :: [String] -> AttrSet -> [Any]
+    : The set to get attribute values from
+
+    # Type
+
+    ```
+    attrVals :: [String] -> AttrSet -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrVals` usage example
+
+    ```nix
+    attrVals ["a" "b" "c"] as
+    => [as.a as.b as.c]
+    ```
+
+    :::
   */
   attrVals =
-    # The list of attributes to fetch from `set`. Each attribute name must exist on the attrbitue set
     nameList:
-    # The set to get attribute values from
     set: map (x: set.${x}) nameList;
 
 
-  /* Return the values of all attributes in the given set, sorted by
-     attribute name.
+  /**
+    Return the values of all attributes in the given set, sorted by
+    attribute name.
 
-     Example:
-       attrValues {c = 3; a = 1; b = 2;}
-       => [1 2 3]
+    # Type
 
-     Type:
-       attrValues :: AttrSet -> [Any]
+    ```
+    attrValues :: AttrSet -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrValues` usage example
+
+    ```nix
+    attrValues {c = 3; a = 1; b = 2;}
+    => [1 2 3]
+    ```
+
+    :::
   */
   attrValues = builtins.attrValues;
 
 
-  /* Given a set of attribute names, return the set of the corresponding
-     attributes from the given set.
+  /**
+    Given a set of attribute names, return the set of the corresponding
+    attributes from the given set.
+
+
+    # Inputs
+
+    `names`
 
-     Example:
-       getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
-       => { a = 1; b = 2; }
+    : A list of attribute names to get out of `set`
 
-     Type:
-       getAttrs :: [String] -> AttrSet -> AttrSet
+    `attrs`
+
+    : The set to get the named attributes from
+
+    # Type
+
+    ```
+    getAttrs :: [String] -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getAttrs` usage example
+
+    ```nix
+    getAttrs [ "a" "b" ] { a = 1; b = 2; c = 3; }
+    => { a = 1; b = 2; }
+    ```
+
+    :::
   */
   getAttrs =
-    # A list of attribute names to get out of `set`
     names:
-    # The set to get the named attributes from
     attrs: genAttrs names (name: attrs.${name});
 
-  /* Collect each attribute named `attr` from a list of attribute
-     sets.  Sets that don't contain the named attribute are ignored.
+  /**
+    Collect each attribute named `attr` from a list of attribute
+    sets.  Sets that don't contain the named attribute are ignored.
+
+    # Inputs
+
+    `attr`
+
+    : The attribute name to get out of the sets.
 
-     Example:
-       catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
-       => [1 2]
+    `list`
 
-     Type:
-       catAttrs :: String -> [AttrSet] -> [Any]
+    : The list of attribute sets to go through
+
+    # Type
+
+    ```
+    catAttrs :: String -> [AttrSet] -> [Any]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.catAttrs` usage example
+
+    ```nix
+    catAttrs "a" [{a = 1;} {b = 0;} {a = 2;}]
+    => [1 2]
+    ```
+
+    :::
   */
   catAttrs = builtins.catAttrs;
 
 
-  /* Filter an attribute set by removing all attributes for which the
-     given predicate return false.
+  /**
+    Filter an attribute set by removing all attributes for which the
+    given predicate return false.
+
+
+    # Inputs
+
+    `pred`
 
-     Example:
-       filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
-       => { foo = 1; }
+    : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
 
-     Type:
-       filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    `set`
+
+    : The attribute set to filter
+
+    # Type
+
+    ```
+    filterAttrs :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.filterAttrs` usage example
+
+    ```nix
+    filterAttrs (n: v: n == "foo") { foo = 1; bar = 2; }
+    => { foo = 1; }
+    ```
+
+    :::
   */
   filterAttrs =
-    # Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
     pred:
-    # The attribute set to filter
     set:
     listToAttrs (concatMap (name: let v = set.${name}; in if pred name v then [(nameValuePair name v)] else []) (attrNames set));
 
 
-  /* Filter an attribute set recursively by removing all attributes for
-     which the given predicate return false.
+  /**
+    Filter an attribute set recursively by removing all attributes for
+    which the given predicate return false.
+
+
+    # Inputs
+
+    `pred`
+
+    : Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
+
+    `set`
+
+    : The attribute set to filter
+
+    # Type
+
+    ```
+    filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```
 
-     Example:
-       filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
-       => { foo = {}; }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.filterAttrsRecursive` usage example
 
-     Type:
-       filterAttrsRecursive :: (String -> Any -> Bool) -> AttrSet -> AttrSet
+    ```nix
+    filterAttrsRecursive (n: v: v != null) { foo = { bar = null; }; }
+    => { foo = {}; }
+    ```
+
+    :::
   */
   filterAttrsRecursive =
-    # Predicate taking an attribute name and an attribute value, which returns `true` to include the attribute, or `false` to exclude the attribute.
     pred:
-    # The attribute set to filter
     set:
     listToAttrs (
       concatMap (name:
@@ -445,59 +694,84 @@ rec {
       ) (attrNames set)
     );
 
-   /*
+   /**
     Like [`lib.lists.foldl'`](#function-library-lib.lists.foldl-prime) but for attribute sets.
     Iterates over every name-value pair in the given attribute set.
     The result of the callback function is often called `acc` for accumulator. It is passed between callbacks from left to right and the final `acc` is the return value of `foldlAttrs`.
 
     Attention:
-      There is a completely different function
-      `lib.foldAttrs`
-      which has nothing to do with this function, despite the similar name.
-
-    Example:
-      foldlAttrs
-        (acc: name: value: {
-          sum = acc.sum + value;
-          names = acc.names ++ [name];
-        })
-        { sum = 0; names = []; }
-        {
-          foo = 1;
-          bar = 10;
-        }
-      ->
-        {
-          sum = 11;
-          names = ["bar" "foo"];
-        }
-
-      foldlAttrs
-        (throw "function not needed")
-        123
-        {};
-      ->
-        123
-
-      foldlAttrs
-        (acc: _: _: acc)
-        3
-        { z = throw "value not needed"; a = throw "value not needed"; };
-      ->
-        3
-
-      The accumulator doesn't have to be an attrset.
-      It can be as simple as a number or string.
-
-      foldlAttrs
-        (acc: _: v: acc * 10 + v)
-        1
-        { z = 1; a = 2; };
-      ->
-        121
-
-    Type:
-      foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
+
+    There is a completely different function `lib.foldAttrs`
+    which has nothing to do with this function, despite the similar name.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
+
+    `init`
+
+    : 2\. Function argument
+
+    `set`
+
+    : 3\. Function argument
+
+    # Type
+
+    ```
+    foldlAttrs :: ( a -> String -> b -> a ) -> a -> { ... :: b } -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.foldlAttrs` usage example
+
+    ```nix
+    foldlAttrs
+      (acc: name: value: {
+        sum = acc.sum + value;
+        names = acc.names ++ [name];
+      })
+      { sum = 0; names = []; }
+      {
+        foo = 1;
+        bar = 10;
+      }
+    ->
+      {
+        sum = 11;
+        names = ["bar" "foo"];
+      }
+
+    foldlAttrs
+      (throw "function not needed")
+      123
+      {};
+    ->
+      123
+
+    foldlAttrs
+      (acc: _: _: acc)
+      3
+      { z = throw "value not needed"; a = throw "value not needed"; };
+    ->
+      3
+
+    The accumulator doesn't have to be an attrset.
+    It can be as simple as a number or string.
+
+    foldlAttrs
+      (acc: _: v: acc * 10 + v)
+      1
+      { z = 1; a = 2; };
+    ->
+      121
+    ```
+
+    :::
   */
   foldlAttrs = f: init: set:
     foldl'
@@ -505,22 +779,44 @@ rec {
       init
       (attrNames set);
 
-  /* Apply fold functions to values grouped by key.
+  /**
+    Apply fold functions to values grouped by key.
+
+
+    # Inputs
+
+    `op`
+
+    : A function, given a value and a collector combines the two.
+
+    `nul`
+
+    : The starting value.
+
+    `list_of_attrs`
+
+    : A list of attribute sets to fold together by key.
+
+    # Type
+
+    ```
+    foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
+    ```
 
-     Example:
-       foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
-       => { a = [ 2 3 ]; }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.foldAttrs` usage example
 
-     Type:
-       foldAttrs :: (Any -> Any -> Any) -> Any -> [AttrSets] -> Any
+    ```nix
+    foldAttrs (item: acc: [item] ++ acc) [] [{ a = 2; } { a = 3; }]
+    => { a = [ 2 3 ]; }
+    ```
 
+    :::
   */
   foldAttrs =
-    # A function, given a value and a collector combines the two.
     op:
-    # The starting value.
     nul:
-    # A list of attribute sets to fold together by key.
     list_of_attrs:
     foldr (n: a:
         foldr (name: o:
@@ -529,26 +825,46 @@ rec {
     ) {} list_of_attrs;
 
 
-  /* Recursively collect sets that verify a given predicate named `pred`
-     from the set `attrs`.  The recursion is stopped when the predicate is
-     verified.
+  /**
+    Recursively collect sets that verify a given predicate named `pred`
+    from the set `attrs`. The recursion is stopped when the predicate is
+    verified.
+
 
-     Example:
-       collect isList { a = { b = ["b"]; }; c = [1]; }
-       => [["b"] [1]]
+    # Inputs
 
-       collect (x: x ? outPath)
-          { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
-       => [{ outPath = "a/"; } { outPath = "b/"; }]
+    `pred`
+
+    : Given an attribute's value, determine if recursion should stop.
+
+    `attrs`
+
+    : The attribute set to recursively collect.
+
+    # Type
 
-     Type:
-       collect :: (AttrSet -> Bool) -> AttrSet -> [x]
+    ```
+    collect :: (AttrSet -> Bool) -> AttrSet -> [x]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.collect` usage example
+
+    ```nix
+    collect isList { a = { b = ["b"]; }; c = [1]; }
+    => [["b"] [1]]
+
+    collect (x: x ? outPath)
+       { a = { outPath = "a/"; }; b = { outPath = "b/"; }; }
+    => [{ outPath = "a/"; } { outPath = "b/"; }]
+    ```
+
+    :::
   */
   collect =
-  # Given an attribute's value, determine if recursion should stop.
-  pred:
-  # The attribute set to recursively collect.
-  attrs:
+    pred:
+    attrs:
     if pred attrs then
       [ attrs ]
     else if isAttrs attrs then
@@ -556,21 +872,39 @@ rec {
     else
       [];
 
-  /* Return the cartesian product of attribute set value combinations.
-
-    Example:
-      cartesianProductOfSets { a = [ 1 2 ]; b = [ 10 20 ]; }
-      => [
-           { a = 1; b = 10; }
-           { a = 1; b = 20; }
-           { a = 2; b = 10; }
-           { a = 2; b = 20; }
-         ]
-     Type:
-       cartesianProductOfSets :: AttrSet -> [AttrSet]
+  /**
+    Return the cartesian product of attribute set value combinations.
+
+
+    # Inputs
+
+    `attrsOfLists`
+
+    : Attribute set with attributes that are lists of values
+
+    # Type
+
+    ```
+    cartesianProductOfSets :: AttrSet -> [AttrSet]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.cartesianProductOfSets` usage example
+
+    ```nix
+    cartesianProductOfSets { a = [ 1 2 ]; b = [ 10 20 ]; }
+    => [
+         { a = 1; b = 10; }
+         { a = 1; b = 20; }
+         { a = 2; b = 10; }
+         { a = 2; b = 20; }
+       ]
+    ```
+
+    :::
   */
   cartesianProductOfSets =
-    # Attribute set with attributes that are lists of values
     attrsOfLists:
     foldl' (listOfAttrs: attrName:
       concatMap (attrs:
@@ -579,76 +913,155 @@ rec {
     ) [{}] (attrNames attrsOfLists);
 
 
-  /* Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
+  /**
+    Utility function that creates a `{name, value}` pair as expected by `builtins.listToAttrs`.
+
+
+    # Inputs
 
-     Example:
-       nameValuePair "some" 6
-       => { name = "some"; value = 6; }
+    `name`
 
-     Type:
-       nameValuePair :: String -> Any -> { name :: String; value :: Any; }
+    : Attribute name
+
+    `value`
+
+    : Attribute value
+
+    # Type
+
+    ```
+    nameValuePair :: String -> Any -> { name :: String; value :: Any; }
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.nameValuePair` usage example
+
+    ```nix
+    nameValuePair "some" 6
+    => { name = "some"; value = 6; }
+    ```
+
+    :::
   */
   nameValuePair =
-    # Attribute name
     name:
-    # Attribute value
     value:
     { inherit name value; };
 
 
-  /* Apply a function to each element in an attribute set, creating a new attribute set.
+  /**
+    Apply a function to each element in an attribute set, creating a new attribute set.
+
+    # Inputs
+
+    `f`
 
-     Example:
-       mapAttrs (name: value: name + "-" + value)
-          { x = "foo"; y = "bar"; }
-       => { x = "x-foo"; y = "y-bar"; }
+    : A function that takes an attribute name and its value, and returns the new value for the attribute.
 
-     Type:
-       mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
+    `attrset`
+
+    : The attribute set to iterate through.
+
+    # Type
+
+    ```
+    mapAttrs :: (String -> Any -> Any) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrs` usage example
+
+    ```nix
+    mapAttrs (name: value: name + "-" + value)
+       { x = "foo"; y = "bar"; }
+    => { x = "x-foo"; y = "y-bar"; }
+    ```
+
+    :::
   */
   mapAttrs = builtins.mapAttrs;
 
 
-  /* Like `mapAttrs`, but allows the name of each attribute to be
-     changed in addition to the value.  The applied function should
-     return both the new name and value as a `nameValuePair`.
+  /**
+    Like `mapAttrs`, but allows the name of each attribute to be
+    changed in addition to the value.  The applied function should
+    return both the new name and value as a `nameValuePair`.
+
+
+    # Inputs
 
-     Example:
-       mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
-          { x = "a"; y = "b"; }
-       => { foo_x = "bar-a"; foo_y = "bar-b"; }
+    `f`
 
-     Type:
-       mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
+    : A function, given an attribute's name and value, returns a new `nameValuePair`.
+
+    `set`
+
+    : Attribute set to map over.
+
+    # Type
+
+    ```
+    mapAttrs' :: (String -> Any -> { name :: String; value :: Any; }) -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrs'` usage example
+
+    ```nix
+    mapAttrs' (name: value: nameValuePair ("foo_" + name) ("bar-" + value))
+       { x = "a"; y = "b"; }
+    => { foo_x = "bar-a"; foo_y = "bar-b"; }
+    ```
+
+    :::
   */
   mapAttrs' =
-    # A function, given an attribute's name and value, returns a new `nameValuePair`.
     f:
-    # Attribute set to map over.
     set:
     listToAttrs (map (attr: f attr set.${attr}) (attrNames set));
 
 
-  /* Call a function for each attribute in the given set and return
-     the result in a list.
+  /**
+    Call a function for each attribute in the given set and return
+    the result in a list.
+
+    # Inputs
+
+    `f`
 
-     Example:
-       mapAttrsToList (name: value: name + value)
-          { x = "a"; y = "b"; }
-       => [ "xa" "yb" ]
+    : A function, given an attribute's name and value, returns a new value.
 
-     Type:
-       mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
+    `attrs`
 
+    : Attribute set to map over.
+
+    # Type
+
+    ```
+    mapAttrsToList :: (String -> a -> b) -> AttrSet -> [b]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mapAttrsToList` usage example
+
+    ```nix
+    mapAttrsToList (name: value: name + value)
+       { x = "a"; y = "b"; }
+    => [ "xa" "yb" ]
+    ```
+
+    :::
   */
   mapAttrsToList =
-    # A function, given an attribute's name and value, returns a new value.
     f:
-    # Attribute set to map over.
     attrs:
     map (name: f name attrs.${name}) (attrNames attrs);
 
-  /*
+  /**
     Deconstruct an attrset to a list of name-value pairs as expected by [`builtins.listToAttrs`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-listToAttrs).
     Each element of the resulting list is an attribute set with these attributes:
     - `name` (string): The name of the attribute
@@ -668,13 +1081,28 @@ rec {
     This is because the `listToAttrs` removes duplicate names and doesn't preserve the order of the list.
     :::
 
-    Example:
-      attrsToList { foo = 1; bar = "asdf"; }
-      => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
+    # Inputs
+
+    `set`
 
-    Type:
-      attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
+    : The attribute set to deconstruct.
+
+    # Type
 
+    ```
+    attrsToList :: AttrSet -> [ { name :: String; value :: Any; } ]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.attrsToList` usage example
+
+    ```nix
+    attrsToList { foo = 1; bar = "asdf"; }
+    => [ { name = "bar"; value = "asdf"; } { name = "foo"; value = 1; } ]
+    ```
+
+    :::
   */
   attrsToList = mapAttrsToList nameValuePair;
 
@@ -705,9 +1133,7 @@ rec {
     ```
   */
   mapAttrsRecursive =
-    # A function that, given an attribute path as a list of strings and the corresponding attribute value, returns a new value.
     f:
-    # Attribute set to recursively map over.
     set:
     mapAttrsRecursiveCond (as: true) f set;
 
@@ -736,12 +1162,8 @@ rec {
     ```
   */
   mapAttrsRecursiveCond =
-    # A function that, given the attribute set the recursion is currently at, determines if to recurse deeper into that attribute set.
     cond:
-    # A function that, given an attribute path as a list of strings and the corresponding attribute value, returns a new value.
-    # The attribute value is either an attribute set for which `cond` returns false, or something other than an attribute set.
     f:
-    # Attribute set to recursively map over.
     set:
     let
       recurse = path:
@@ -754,48 +1176,95 @@ rec {
     recurse [ ] set;
 
 
-  /* Generate an attribute set by mapping a function over a list of
-     attribute names.
+  /**
+    Generate an attribute set by mapping a function over a list of
+    attribute names.
+
+
+    # Inputs
+
+    `names`
+
+    : Names of values in the resulting attribute set.
+
+    `f`
+
+    : A function, given the name of the attribute, returns the attribute's value.
+
+    # Type
+
+    ```
+    genAttrs :: [ String ] -> (String -> Any) -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.genAttrs` usage example
 
-     Example:
-       genAttrs [ "foo" "bar" ] (name: "x_" + name)
-       => { foo = "x_foo"; bar = "x_bar"; }
+    ```nix
+    genAttrs [ "foo" "bar" ] (name: "x_" + name)
+    => { foo = "x_foo"; bar = "x_bar"; }
+    ```
 
-     Type:
-       genAttrs :: [ String ] -> (String -> Any) -> AttrSet
+    :::
   */
   genAttrs =
-    # Names of values in the resulting attribute set.
     names:
-    # A function, given the name of the attribute, returns the attribute's value.
     f:
     listToAttrs (map (n: nameValuePair n (f n)) names);
 
 
-  /* Check whether the argument is a derivation. Any set with
-     `{ type = "derivation"; }` counts as a derivation.
+  /**
+    Check whether the argument is a derivation. Any set with
+    `{ type = "derivation"; }` counts as a derivation.
+
 
-     Example:
-       nixpkgs = import <nixpkgs> {}
-       isDerivation nixpkgs.ruby
-       => true
-       isDerivation "foobar"
-       => false
+    # Inputs
 
-     Type:
-       isDerivation :: Any -> Bool
+    `value`
+
+    : Value to check.
+
+    # Type
+
+    ```
+    isDerivation :: Any -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.isDerivation` usage example
+
+    ```nix
+    nixpkgs = import <nixpkgs> {}
+    isDerivation nixpkgs.ruby
+    => true
+    isDerivation "foobar"
+    => false
+    ```
+
+    :::
   */
   isDerivation =
-    # Value to check.
     value: value.type or null == "derivation";
 
-   /* Converts a store path to a fake derivation.
+   /**
+    Converts a store path to a fake derivation.
+
+
+    # Inputs
+
+    `path`
 
-      Type:
-        toDerivation :: Path -> Derivation
-   */
+    : A store path to convert to a derivation.
+
+    # Type
+
+    ```
+    toDerivation :: Path -> Derivation
+    ```
+  */
    toDerivation =
-     # A store path to convert to a derivation.
      path:
      let
        path' = builtins.storePath path;
@@ -810,42 +1279,85 @@ rec {
     in res;
 
 
-  /* If `cond` is true, return the attribute set `as`,
-     otherwise an empty attribute set.
+  /**
+    If `cond` is true, return the attribute set `as`,
+    otherwise an empty attribute set.
+
+
+    # Inputs
+
+    `cond`
 
-     Example:
-       optionalAttrs (true) { my = "set"; }
-       => { my = "set"; }
-       optionalAttrs (false) { my = "set"; }
-       => { }
+    : Condition under which the `as` attribute set is returned.
+
+    `as`
+
+    : The attribute set to return if `cond` is `true`.
+
+    # Type
+
+    ```
+    optionalAttrs :: Bool -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.optionalAttrs` usage example
+
+    ```nix
+    optionalAttrs (true) { my = "set"; }
+    => { my = "set"; }
+    optionalAttrs (false) { my = "set"; }
+    => { }
+    ```
 
-     Type:
-       optionalAttrs :: Bool -> AttrSet -> AttrSet
+    :::
   */
   optionalAttrs =
-    # Condition under which the `as` attribute set is returned.
     cond:
-    # The attribute set to return if `cond` is `true`.
     as:
     if cond then as else {};
 
 
-  /* Merge sets of attributes and use the function `f` to merge attributes
-     values.
+  /**
+    Merge sets of attributes and use the function `f` to merge attributes
+    values.
+
+
+    # Inputs
+
+    `names`
 
-     Example:
-       zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; }
+    : List of attribute names to zip.
 
-     Type:
-       zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    `f`
+
+    : A function, accepts an attribute name, all the values, and returns a combined value.
+
+    `sets`
+
+    : List of values from the list of attribute sets.
+
+    # Type
+
+    ```
+    zipAttrsWithNames :: [ String ] -> (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrsWithNames` usage example
+
+    ```nix
+    zipAttrsWithNames ["a"] (name: vs: vs) [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; }
+    ```
+
+    :::
   */
   zipAttrsWithNames =
-    # List of attribute names to zip.
     names:
-    # A function, accepts an attribute name, all the values, and returns a combined value.
     f:
-    # List of values from the list of attribute sets.
     sets:
     listToAttrs (map (name: {
       inherit name;
@@ -853,52 +1365,91 @@ rec {
     }) names);
 
 
-  /* Merge sets of attributes and use the function f to merge attribute values.
-     Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
+  /**
+    Merge sets of attributes and use the function f to merge attribute values.
+    Like `lib.attrsets.zipAttrsWithNames` with all key names are passed for `names`.
 
-     Implementation note: Common names appear multiple times in the list of
-     names, hopefully this does not affect the system because the maximal
-     laziness avoid computing twice the same expression and `listToAttrs` does
-     not care about duplicated attribute names.
+    Implementation note: Common names appear multiple times in the list of
+    names, hopefully this does not affect the system because the maximal
+    laziness avoid computing twice the same expression and `listToAttrs` does
+    not care about duplicated attribute names.
 
-     Example:
-       zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; b = ["z"]; }
+    # Type
+
+    ```
+    zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrsWith` usage example
 
-     Type:
-       zipAttrsWith :: (String -> [ Any ] -> Any) -> [ AttrSet ] -> AttrSet
+    ```nix
+    zipAttrsWith (name: values: values) [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; b = ["z"]; }
+    ```
+
+    :::
   */
   zipAttrsWith =
     builtins.zipAttrsWith or (f: sets: zipAttrsWithNames (concatMap attrNames sets) f sets);
 
 
-  /* Merge sets of attributes and combine each attribute value in to a list.
+  /**
+    Merge sets of attributes and combine each attribute value in to a list.
+
+    Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
+
+    # Type
+
+    ```
+    zipAttrs :: [ AttrSet ] -> AttrSet
+    ```
 
-     Like `lib.attrsets.zipAttrsWith` with `(name: values: values)` as the function.
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.zipAttrs` usage example
 
-     Example:
-       zipAttrs [{a = "x";} {a = "y"; b = "z";}]
-       => { a = ["x" "y"]; b = ["z"]; }
+    ```nix
+    zipAttrs [{a = "x";} {a = "y"; b = "z";}]
+    => { a = ["x" "y"]; b = ["z"]; }
+    ```
 
-     Type:
-       zipAttrs :: [ AttrSet ] -> AttrSet
+    :::
   */
   zipAttrs = zipAttrsWith (name: values: values);
 
-  /*
+  /**
     Merge a list of attribute sets together using the `//` operator.
     In case of duplicate attributes, values from later list elements take precedence over earlier ones.
     The result is the same as `foldl mergeAttrs { }`, but the performance is better for large inputs.
     For n list elements, each with an attribute set containing m unique attributes, the complexity of this operation is O(nm log n).
 
-    Type:
-      mergeAttrsList :: [ Attrs ] -> Attrs
 
-    Example:
-      mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
-      => { a = 0; b = 1; c = 2; d = 3; }
-      mergeAttrsList [ { a = 0; } { a = 1; } ]
-      => { a = 1; }
+    # Inputs
+
+    `list`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    mergeAttrsList :: [ Attrs ] -> Attrs
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.mergeAttrsList` usage example
+
+    ```nix
+    mergeAttrsList [ { a = 0; b = 1; } { c = 2; d = 3; } ]
+    => { a = 0; b = 1; c = 2; d = 3; }
+    mergeAttrsList [ { a = 0; } { a = 1; } ]
+    => { a = 1; }
+    ```
+
+    :::
   */
   mergeAttrsList = list:
     let
@@ -922,42 +1473,65 @@ rec {
       binaryMerge 0 (length list);
 
 
-  /* Does the same as the update operator '//' except that attributes are
-     merged until the given predicate is verified.  The predicate should
-     accept 3 arguments which are the path to reach the attribute, a part of
-     the first attribute set and a part of the second attribute set.  When
-     the predicate is satisfied, the value of the first attribute set is
-     replaced by the value of the second attribute set.
-
-     Example:
-       recursiveUpdateUntil (path: l: r: path == ["foo"]) {
-         # first attribute set
-         foo.bar = 1;
-         foo.baz = 2;
-         bar = 3;
-       } {
-         #second attribute set
-         foo.bar = 1;
-         foo.quz = 2;
-         baz = 4;
-       }
-
-       => {
-         foo.bar = 1; # 'foo.*' from the second set
-         foo.quz = 2; #
-         bar = 3;     # 'bar' from the first set
-         baz = 4;     # 'baz' from the second set
-       }
-
-     Type:
-       recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
+  /**
+    Does the same as the update operator '//' except that attributes are
+    merged until the given predicate is verified.  The predicate should
+    accept 3 arguments which are the path to reach the attribute, a part of
+    the first attribute set and a part of the second attribute set.  When
+    the predicate is satisfied, the value of the first attribute set is
+    replaced by the value of the second attribute set.
+
+
+    # Inputs
+
+    `pred`
+
+    : Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
+
+    `lhs`
+
+    : Left attribute set of the merge.
+
+    `rhs`
+
+    : Right attribute set of the merge.
+
+    # Type
+
+    ```
+    recursiveUpdateUntil :: ( [ String ] -> AttrSet -> AttrSet -> Bool ) -> AttrSet -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recursiveUpdateUntil` usage example
+
+    ```nix
+    recursiveUpdateUntil (path: l: r: path == ["foo"]) {
+      # first attribute set
+      foo.bar = 1;
+      foo.baz = 2;
+      bar = 3;
+    } {
+      #second attribute set
+      foo.bar = 1;
+      foo.quz = 2;
+      baz = 4;
+    }
+
+    => {
+      foo.bar = 1; # 'foo.*' from the second set
+      foo.quz = 2; #
+      bar = 3;     # 'bar' from the first set
+      baz = 4;     # 'baz' from the second set
+    }
+    ```
+
+    :::
   */
   recursiveUpdateUntil =
-    # Predicate, taking the path to the current attribute as a list of strings for attribute names, and the two values at that path from the original arguments.
     pred:
-    # Left attribute set of the merge.
     lhs:
-    # Right attribute set of the merge.
     rhs:
     let f = attrPath:
       zipAttrsWith (n: values:
@@ -971,51 +1545,90 @@ rec {
     in f [] [rhs lhs];
 
 
-  /* A recursive variant of the update operator ‘//’.  The recursion
-     stops when one of the attribute values is not an attribute set,
-     in which case the right hand side value takes precedence over the
-     left hand side value.
+  /**
+    A recursive variant of the update operator ‘//’.  The recursion
+    stops when one of the attribute values is not an attribute set,
+    in which case the right hand side value takes precedence over the
+    left hand side value.
+
+
+    # Inputs
+
+    `lhs`
+
+    : Left attribute set of the merge.
+
+    `rhs`
+
+    : Right attribute set of the merge.
+
+    # Type
+
+    ```
+    recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
+    ```
 
-     Example:
-       recursiveUpdate {
-         boot.loader.grub.enable = true;
-         boot.loader.grub.device = "/dev/hda";
-       } {
-         boot.loader.grub.device = "";
-       }
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recursiveUpdate` usage example
 
-       returns: {
-         boot.loader.grub.enable = true;
-         boot.loader.grub.device = "";
-       }
+    ```nix
+    recursiveUpdate {
+      boot.loader.grub.enable = true;
+      boot.loader.grub.device = "/dev/hda";
+    } {
+      boot.loader.grub.device = "";
+    }
+
+    returns: {
+      boot.loader.grub.enable = true;
+      boot.loader.grub.device = "";
+    }
+    ```
 
-     Type:
-       recursiveUpdate :: AttrSet -> AttrSet -> AttrSet
+    :::
   */
   recursiveUpdate =
-    # Left attribute set of the merge.
     lhs:
-    # Right attribute set of the merge.
     rhs:
     recursiveUpdateUntil (path: lhs: rhs: !(isAttrs lhs && isAttrs rhs)) lhs rhs;
 
 
-  /*
+  /**
     Recurse into every attribute set of the first argument and check that:
     - Each attribute path also exists in the second argument.
     - If the attribute's value is not a nested attribute set, it must have the same value in the right argument.
 
-     Example:
-       matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
-       => true
 
-     Type:
-       matchAttrs :: AttrSet -> AttrSet -> Bool
+    # Inputs
+
+    `pattern`
+
+    : Attribute set structure to match
+
+    `attrs`
+
+    : Attribute set to check
+
+    # Type
+
+    ```
+    matchAttrs :: AttrSet -> AttrSet -> Bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.matchAttrs` usage example
+
+    ```nix
+    matchAttrs { cpu = {}; } { cpu = { bits = 64; }; }
+    => true
+    ```
+
+    :::
   */
   matchAttrs =
-    # Attribute set structure to match
     pattern:
-    # Attribute set to check
     attrs:
     assert isAttrs pattern;
     all
@@ -1034,161 +1647,340 @@ rec {
     )
     (attrNames pattern);
 
-  /* Override only the attributes that are already present in the old set
+  /**
+    Override only the attributes that are already present in the old set
     useful for deep-overriding.
 
-    Example:
-      overrideExisting {} { a = 1; }
-      => {}
-      overrideExisting { b = 2; } { a = 1; }
-      => { b = 2; }
-      overrideExisting { a = 3; b = 2; } { a = 1; }
-      => { a = 1; b = 2; }
 
-    Type:
-      overrideExisting :: AttrSet -> AttrSet -> AttrSet
+    # Inputs
+
+    `old`
+
+    : Original attribute set
+
+    `new`
+
+    : Attribute set with attributes to override in `old`.
+
+    # Type
+
+    ```
+    overrideExisting :: AttrSet -> AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.overrideExisting` usage example
+
+    ```nix
+    overrideExisting {} { a = 1; }
+    => {}
+    overrideExisting { b = 2; } { a = 1; }
+    => { b = 2; }
+    overrideExisting { a = 3; b = 2; } { a = 1; }
+    => { a = 1; b = 2; }
+    ```
+
+    :::
   */
   overrideExisting =
-    # Original attribute set
     old:
-    # Attribute set with attributes to override in `old`.
     new:
     mapAttrs (name: value: new.${name} or value) old;
 
 
-  /* Turns a list of strings into a human-readable description of those
+  /**
+    Turns a list of strings into a human-readable description of those
     strings represented as an attribute path. The result of this function is
     not intended to be machine-readable.
     Create a new attribute set with `value` set at the nested attribute location specified in `attrPath`.
 
-    Example:
-      showAttrPath [ "foo" "10" "bar" ]
-      => "foo.\"10\".bar"
-      showAttrPath []
-      => "<root attribute path>"
 
-    Type:
-      showAttrPath :: [String] -> String
+    # Inputs
+
+    `path`
+
+    : Attribute path to render to a string
+
+    # Type
+
+    ```
+    showAttrPath :: [String] -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.showAttrPath` usage example
+
+    ```nix
+    showAttrPath [ "foo" "10" "bar" ]
+    => "foo.\"10\".bar"
+    showAttrPath []
+    => "<root attribute path>"
+    ```
+
+    :::
   */
   showAttrPath =
-    # Attribute path to render to a string
     path:
     if path == [] then "<root attribute path>"
     else concatMapStringsSep "." escapeNixIdentifier path;
 
 
-  /* Get a package output.
-     If no output is found, fallback to `.out` and then to the default.
+  /**
+    Get a package output.
+    If no output is found, fallback to `.out` and then to the default.
+
+
+    # Inputs
+
+    `output`
 
-     Example:
-       getOutput "dev" pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    : 1\. Function argument
 
-     Type:
-       getOutput :: String -> Derivation -> String
+    `pkg`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    getOutput :: String -> Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getOutput` usage example
+
+    ```nix
+    getOutput "dev" pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    ```
+
+    :::
   */
   getOutput = output: pkg:
     if ! pkg ? outputSpecified || ! pkg.outputSpecified
       then pkg.${output} or pkg.out or pkg
       else pkg;
 
-  /* Get a package's `bin` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `bin` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getBin pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r"
+    : The package whose `bin` output will be retrieved.
 
-     Type:
-       getBin :: Derivation -> String
+    # Type
+
+    ```
+    getBin :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getBin` usage example
+
+    ```nix
+    getBin pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r"
+    ```
+
+    :::
   */
   getBin = getOutput "bin";
 
 
-  /* Get a package's `lib` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `lib` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getLib pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
+    : The package whose `lib` output will be retrieved.
 
-     Type:
-       getLib :: Derivation -> String
+    # Type
+
+    ```
+    getLib :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getLib` usage example
+
+    ```nix
+    getLib pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-lib"
+    ```
+
+    :::
   */
   getLib = getOutput "lib";
 
 
-  /* Get a package's `dev` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `dev` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
 
-     Example:
-       getDev pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    : The package whose `dev` output will be retrieved.
+
+    # Type
+
+    ```
+    getDev :: Derivation -> String
+    ```
 
-     Type:
-       getDev :: Derivation -> String
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getDev` usage example
+
+    ```nix
+    getDev pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-dev"
+    ```
+
+    :::
   */
   getDev = getOutput "dev";
 
 
-  /* Get a package's `man` output.
-     If the output does not exist, fallback to `.out` and then to the default.
+  /**
+    Get a package's `man` output.
+    If the output does not exist, fallback to `.out` and then to the default.
+
+    # Inputs
+
+    `pkg`
+
+    : The package whose `man` output will be retrieved.
+
+    # Type
+
+    ```
+    getMan :: Derivation -> String
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.getMan` usage example
 
-     Example:
-       getMan pkgs.openssl
-       => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
+    ```nix
+    getMan pkgs.openssl
+    => "/nix/store/9rz8gxhzf8sw4kf2j2f1grr49w8zx5vj-openssl-1.0.1r-man"
+    ```
 
-     Type:
-       getMan :: Derivation -> String
+    :::
   */
   getMan = getOutput "man";
 
-  /* Pick the outputs of packages to place in `buildInputs`
+  /**
+    Pick the outputs of packages to place in `buildInputs`
+
+    # Inputs
 
-   Type: chooseDevOutputs :: [Derivation] -> [String]
+    `pkgs`
 
+    : List of packages.
+
+    # Type
+
+    ```
+    chooseDevOutputs :: [Derivation] -> [String]
+    ```
   */
   chooseDevOutputs = builtins.map getDev;
 
-  /* Make various Nix tools consider the contents of the resulting
-     attribute set when looking for what to build, find, etc.
+  /**
+    Make various Nix tools consider the contents of the resulting
+    attribute set when looking for what to build, find, etc.
 
-     This function only affects a single attribute set; it does not
-     apply itself recursively for nested attribute sets.
+    This function only affects a single attribute set; it does not
+    apply itself recursively for nested attribute sets.
 
-     Example:
-       { pkgs ? import <nixpkgs> {} }:
-       {
-         myTools = pkgs.lib.recurseIntoAttrs {
-           inherit (pkgs) hello figlet;
-         };
-       }
 
-     Type:
-       recurseIntoAttrs :: AttrSet -> AttrSet
+    # Inputs
+
+    `attrs`
+
+    : An attribute set to scan for derivations.
+
+    # Type
 
-   */
+    ```
+    recurseIntoAttrs :: AttrSet -> AttrSet
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.attrsets.recurseIntoAttrs` usage example
+
+    ```nix
+    { pkgs ? import <nixpkgs> {} }:
+    {
+      myTools = pkgs.lib.recurseIntoAttrs {
+        inherit (pkgs) hello figlet;
+      };
+    }
+    ```
+
+    :::
+  */
   recurseIntoAttrs =
-    # An attribute set to scan for derivations.
     attrs:
     attrs // { recurseForDerivations = true; };
 
-  /* Undo the effect of recurseIntoAttrs.
+  /**
+    Undo the effect of recurseIntoAttrs.
 
-     Type:
-       dontRecurseIntoAttrs :: AttrSet -> AttrSet
-   */
+
+    # Inputs
+
+    `attrs`
+
+    : An attribute set to not scan for derivations.
+
+    # Type
+
+    ```
+    dontRecurseIntoAttrs :: AttrSet -> AttrSet
+    ```
+  */
   dontRecurseIntoAttrs =
-    # An attribute set to not scan for derivations.
     attrs:
     attrs // { recurseForDerivations = false; };
 
-  /* `unionOfDisjoint x y` is equal to `x // y // z` where the
-     attrnames in `z` are the intersection of the attrnames in `x` and
-     `y`, and all values `assert` with an error message.  This
-      operator is commutative, unlike (//).
+  /**
+    `unionOfDisjoint x y` is equal to `x // y // z` where the
+    attrnames in `z` are the intersection of the attrnames in `x` and
+    `y`, and all values `assert` with an error message.  This
+     operator is commutative, unlike (//).
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
 
-     Type: unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    unionOfDisjoint :: AttrSet -> AttrSet -> AttrSet
+    ```
   */
   unionOfDisjoint = x: y:
     let
diff --git a/nixpkgs/lib/customisation.nix b/nixpkgs/lib/customisation.nix
index 7be412bac353..66638b63342a 100644
--- a/nixpkgs/lib/customisation.nix
+++ b/nixpkgs/lib/customisation.nix
@@ -306,18 +306,129 @@ rec {
     in if drv == null then null else
       deepSeq drv' drv';
 
-  /* Make a set of packages with a common scope. All packages called
-     with the provided `callPackage` will be evaluated with the same
-     arguments. Any package in the set may depend on any other. The
-     `overrideScope'` function allows subsequent modification of the package
-     set in a consistent way, i.e. all packages in the set will be
-     called with the overridden packages. The package sets may be
-     hierarchical: the packages in the set are called with the scope
-     provided by `newScope` and the set provides a `newScope` attribute
-     which can form the parent scope for later package sets.
+  /**
+    Make an attribute set (a "scope") from functions that take arguments from that same attribute set.
+    See [](#ex-makeScope) for how to use it.
 
-     Type:
-       makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> AttrSet
+    # Inputs
+
+    1. `newScope` (`AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a`)
+
+       A function that takes an attribute set `attrs` and returns what ends up as `callPackage` in the output.
+
+       Typical values are `callPackageWith` or the output attribute `newScope`.
+
+    2. `f` (`AttrSet -> AttrSet`)
+
+       A function that takes an attribute set as returned by `makeScope newScope f` (a "scope") and returns any attribute set.
+
+       This function is used to compute the fixpoint of the resulting scope using `callPackage`.
+       Its argument is the lazily evaluated reference to the value of that fixpoint, and is typically called `self` or `final`.
+
+       See [](#ex-makeScope) for how to use it.
+       See [](#sec-functions-library-fixedPoints) for details on fixpoint computation.
+
+    # Output
+
+    `makeScope` returns an attribute set of a form called `scope`, which also contains the final attributes produced by `f`:
+
+    ```
+    scope :: {
+      callPackage :: ((AttrSet -> a) | Path) -> AttrSet -> a
+      newScope = AttrSet -> scope
+      overrideScope = (scope -> scope -> AttrSet) -> scope
+      packages :: AttrSet -> AttrSet
+    }
+    ```
+
+    - `callPackage` (`((AttrSet -> a) | Path) -> AttrSet -> a`)
+
+      A function that
+
+      1. Takes a function `p`, or a path to a Nix file that contains a function `p`, which takes an attribute set and returns value of arbitrary type `a`,
+      2. Takes an attribute set `args` with explicit attributes to pass to `p`,
+      3. Calls `f` with attributes from the original attribute set `attrs` passed to `newScope` updated with `args, i.e. `attrs // args`, if they match the attributes in the argument of `p`.
+
+      All such functions `p` will be called with the same value for `attrs`.
+
+      See [](#ex-makeScope-callPackage) for how to use it.
+
+    - `newScope` (`AttrSet -> scope`)
+
+      Takes an attribute set `attrs` and returns a scope that extends the original scope.
+
+    - `overrideScope` (`(scope -> scope -> AttrSet) -> scope`)
+
+      Takes a function `g` of the form `final: prev: { # attributes }` to act as an overlay on `f`, and returns a new scope with values determined by `extends g f`.
+      See [](https://nixos.org/manual/nixpkgs/unstable/#function-library-lib.fixedPoints.extends) for details.
+
+      This allows subsequent modification of the final attribute set in a consistent way, i.e. all functions `p` invoked with `callPackage` will be called with the modified values.
+
+    - `packages` (`AttrSet -> AttrSet`)
+
+      The value of the argument `f` to `makeScope`.
+
+    - final attributes
+
+      The final values returned by `f`.
+
+    # Examples
+
+    :::{#ex-makeScope .example}
+    # Create an interdependent package set on top of `pkgs`
+
+    The functions in `foo.nix` and `bar.nix` can depend on each other, in the sense that `foo.nix` can contain a function that expects `bar` as an attribute in its argument.
+
+    ```nix
+    let
+      pkgs = import <nixpkgs> { };
+    in
+    pkgs.lib.makeScope pkgs.newScope (self: {
+      foo = self.callPackage ./foo.nix { };
+      bar = self.callPackage ./bar.nix { };
+    })
+    ```
+
+    evaluates to
+
+    ```nix
+    {
+      callPackage = «lambda»;
+      newScope = «lambda»;
+      overrideScope = «lambda»;
+      packages = «lambda»;
+      foo = «derivation»;
+      bar = «derivation»;
+    }
+    ```
+    :::
+
+    :::{#ex-makeScope-callPackage .example}
+    # Using `callPackage` from a scope
+
+    ```nix
+    let
+      pkgs = import <nixpkgs> { };
+      inherit (pkgs) lib;
+      scope = lib.makeScope lib.callPackageWith (self: { a = 1; b = 2; });
+      three = scope.callPackage ({ a, b }: a + b) { };
+      four = scope.callPackage ({ a, b }: a + b) { a = 2; };
+    in
+    [ three four ]
+    ```
+
+    evaluates to
+
+    ```nix
+    [ 3 4 ]
+    ```
+    :::
+
+    # Type
+
+    ```
+    makeScope :: (AttrSet -> ((AttrSet -> a) | Path) -> AttrSet -> a) -> (AttrSet -> AttrSet) -> scope
+    ```
   */
   makeScope = newScope: f:
     let self = f self // {
diff --git a/nixpkgs/lib/deprecated.nix b/nixpkgs/lib/deprecated.nix
index ed14e04bbd68..b76622b5d842 100644
--- a/nixpkgs/lib/deprecated.nix
+++ b/nixpkgs/lib/deprecated.nix
@@ -1,14 +1,37 @@
 { lib }:
-let
-    inherit (builtins) head tail isList isAttrs isInt attrNames;
-
-in
-
-with lib.lists;
-with lib.attrsets;
-with lib.strings;
 
-rec {
+let
+  inherit (lib)
+    and
+    any
+    attrByPath
+    attrNames
+    compare
+    concat
+    concatMap
+    elem
+    filter
+    foldl
+    foldr
+    genericClosure
+    head
+    imap1
+    init
+    isAttrs
+    isFunction
+    isInt
+    isList
+    lists
+    listToAttrs
+    mapAttrs
+    mergeAttrs
+    meta
+    nameValuePair
+    tail
+    toList
+    ;
+
+  inherit (lib.attrsets) removeAttrs;
 
   # returns default if env var is not set
   maybeEnv = name: default:
@@ -26,7 +49,7 @@ rec {
         base = (setAttrMerge "passthru" {} (f arg)
                         ( z: z // {
                             function = foldArgs merger f arg;
-                            args = (lib.attrByPath ["passthru" "args"] {} z) // x;
+                            args = (attrByPath ["passthru" "args"] {} z) // x;
                           } ));
         withStdOverrides = base // {
           override = base.passthru.function;
@@ -77,11 +100,11 @@ rec {
   # Output : are reqs satisfied? It's asserted.
   checkReqs = attrSet: argList: condList:
   (
-    foldr lib.and true
+    foldr and true
       (map (x: let name = (head x); in
 
         ((checkFlag attrSet name) ->
-        (foldr lib.and true
+        (foldr and true
         (map (y: let val=(getValue attrSet argList y); in
                 (val!=null) && (val!=false))
         (tail x))))) condList));
@@ -159,11 +182,11 @@ rec {
 
   closePropagationSlow = list: (uniqList {inputList = (innerClosePropagation [] list);});
 
-  # This is an optimisation of lib.closePropagation which avoids the O(n^2) behavior
+  # This is an optimisation of closePropagation which avoids the O(n^2) behavior
   # Using a list of derivations, it generates the full closure of the propagatedXXXBuildInputs
   # The ordering / sorting / comparison is done based on the `outPath`
   # attribute of each derivation.
-  # On some benchmarks, it performs up to 15 times faster than lib.closePropagation.
+  # On some benchmarks, it performs up to 15 times faster than closePropagation.
   # See https://github.com/NixOS/nixpkgs/pull/194391 for details.
   closePropagationFast = list:
     builtins.map (x: x.val) (builtins.genericClosure {
@@ -250,10 +273,10 @@ rec {
   # foldArgs, composedArgsAndFun or applyAndFun. Example: composableDerivation in all-packages.nix
   mergeAttrByFunc = x: y:
     let
-          mergeAttrBy2 = { mergeAttrBy = lib.mergeAttrs; }
+          mergeAttrBy2 = { mergeAttrBy = mergeAttrs; }
                       // (maybeAttr "mergeAttrBy" {} x)
                       // (maybeAttr "mergeAttrBy" {} y); in
-    foldr lib.mergeAttrs {} [
+    foldr mergeAttrs {} [
       x y
       (mapAttrs ( a: v: # merge special names using given functions
           if x ? ${a}
@@ -273,9 +296,9 @@ rec {
 
   # sane defaults (same name as attr name so that inherit can be used)
   mergeAttrBy = # { buildInputs = concatList; [...]; passthru = mergeAttr; [..]; }
-    listToAttrs (map (n: nameValuePair n lib.concat)
+    listToAttrs (map (n: nameValuePair n concat)
       [ "nativeBuildInputs" "buildInputs" "propagatedBuildInputs" "configureFlags" "prePhases" "postAll" "patches" ])
-    // listToAttrs (map (n: nameValuePair n lib.mergeAttrs) [ "passthru" "meta" "cfg" "flags" ])
+    // listToAttrs (map (n: nameValuePair n mergeAttrs) [ "passthru" "meta" "cfg" "flags" ])
     // listToAttrs (map (n: nameValuePair n (a: b: "${a}\n${b}") ) [ "preConfigure" "postInstall" ])
   ;
 
@@ -283,7 +306,7 @@ rec {
       if isAttrs x then
           if x ? outPath then "derivation"
           else "attrs"
-      else if lib.isFunction x then "function"
+      else if isFunction x then "function"
       else if isList x then "list"
       else if x == true then "bool"
       else if x == false then "bool"
@@ -304,4 +327,47 @@ rec {
   fakeHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
   fakeSha256 = "0000000000000000000000000000000000000000000000000000000000000000";
   fakeSha512 = "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
+
+in
+
+# Everything in this attrset is the public interface of the file.
+{
+  inherit
+    checkFlag
+    checkReqs
+    closePropagation
+    closePropagationFast
+    closePropagationSlow
+    condConcat
+    defaultMerge
+    defaultMergeArg
+    fakeHash
+    fakeSha256
+    fakeSha512
+    foldArgs
+    getValue
+    ifEnable
+    imap
+    innerClosePropagation
+    innerModifySumArgs
+    lazyGenericClosure
+    mapAttrsFlatten
+    maybeAttr
+    maybeAttrNullable
+    maybeEnv
+    mergeAttrBy
+    mergeAttrByFunc
+    mergeAttrsByFuncDefaults
+    mergeAttrsByFuncDefaultsClean
+    mergeAttrsConcatenateValues
+    mergeAttrsNoOverride
+    mergeAttrsWithFunc
+    modifySumArgs
+    nixType
+    nvs
+    setAttr
+    setAttrMerge
+    uniqList
+    uniqListExt
+    ;
 }
diff --git a/nixpkgs/lib/generators.nix b/nixpkgs/lib/generators.nix
index ed59654cc07e..5f42a98de709 100644
--- a/nixpkgs/lib/generators.nix
+++ b/nixpkgs/lib/generators.nix
@@ -14,15 +14,58 @@
  * Documentation in the manual, #sec-generators
  */
 { lib }:
-with (lib).trivial;
-let
-  libStr = lib.strings;
-  libAttr = lib.attrsets;
-
-  inherit (lib) isFunction;
-in
 
-rec {
+let
+  inherit (lib)
+    addErrorContext
+    assertMsg
+    attrNames
+    concatLists
+    concatMapStringsSep
+    concatStrings
+    concatStringsSep
+    const
+    elem
+    escape
+    filter
+    flatten
+    foldl
+    functionArgs  # Note: not the builtin; considers `__functor` in attrsets.
+    gvariant
+    hasInfix
+    head
+    id
+    init
+    isAttrs
+    isBool
+    isDerivation
+    isFloat
+    isFunction    # Note: not the builtin; considers `__functor` in attrsets.
+    isInt
+    isList
+    isPath
+    isString
+    last
+    length
+    mapAttrs
+    mapAttrsToList
+    optionals
+    recursiveUpdate
+    replaceStrings
+    reverseList
+    splitString
+    tail
+    toList
+    ;
+
+  inherit (lib.strings)
+    escapeNixIdentifier
+    floatToString
+    match
+    split
+    toJSON
+    typeOf
+    ;
 
   ## -- HELPER FUNCTIONS & DEFAULTS --
 
@@ -30,13 +73,13 @@ rec {
    * The builtin `toString` function has some strange defaults,
    * suitable for bash scripts but not much else.
    */
-  mkValueStringDefault = {}: v: with builtins;
+  mkValueStringDefault = {}: v:
     let err = t: v: abort
           ("generators.mkValueStringDefault: " +
            "${t} not supported: ${toPretty {} v}");
     in   if isInt      v then toString v
     # convert derivations to store paths
-    else if lib.isDerivation v then toString v
+    else if isDerivation v then toString v
     # we default to not quoting strings
     else if isString   v then v
     # isString returns "1", which is not a good default
@@ -53,7 +96,7 @@ rec {
     # Floats currently can't be converted to precise strings,
     # condition warning on nix version once this isn't a problem anymore
     # See https://github.com/NixOS/nix/pull/3480
-    else if isFloat    v then libStr.floatToString v
+    else if isFloat    v then floatToString v
     else err "this value is" (toString v);
 
 
@@ -69,7 +112,7 @@ rec {
   mkKeyValueDefault = {
     mkValueString ? mkValueStringDefault {}
   }: sep: k: v:
-    "${libStr.escape [sep] k}${sep}${mkValueString v}";
+    "${escape [sep] k}${sep}${mkValueString v}";
 
 
   ## -- FILE FORMAT GENERATORS --
@@ -86,9 +129,9 @@ rec {
   }:
   let mkLine = k: v: indent + mkKeyValue k v + "\n";
       mkLines = if listsAsDuplicateKeys
-        then k: v: map (mkLine k) (if lib.isList v then v else [v])
+        then k: v: map (mkLine k) (if isList v then v else [v])
         else k: v: [ (mkLine k v) ];
-  in attrs: libStr.concatStrings (lib.concatLists (libAttr.mapAttrsToList mkLines attrs));
+  in attrs: concatStrings (concatLists (mapAttrsToList mkLines attrs));
 
 
   /* Generate an INI-style config file from an
@@ -113,7 +156,7 @@ rec {
    */
   toINI = {
     # apply transformations (e.g. escapes) to section names
-    mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
+    mkSectionName ? (name: escape [ "[" "]" ] name),
     # format a setting line from key and value
     mkKeyValue    ? mkKeyValueDefault {} "=",
     # allow lists as values for duplicate keys
@@ -122,8 +165,8 @@ rec {
     let
         # map function to string for each key val
         mapAttrsToStringsSep = sep: mapFn: attrs:
-          libStr.concatStringsSep sep
-            (libAttr.mapAttrsToList mapFn attrs);
+          concatStringsSep sep
+            (mapAttrsToList mapFn attrs);
         mkSection = sectName: sectValues: ''
           [${mkSectionName sectName}]
         '' + toKeyValue { inherit mkKeyValue listsAsDuplicateKeys; } sectValues;
@@ -164,7 +207,7 @@ rec {
    */
   toINIWithGlobalSection = {
     # apply transformations (e.g. escapes) to section names
-    mkSectionName ? (name: libStr.escape [ "[" "]" ] name),
+    mkSectionName ? (name: escape [ "[" "]" ] name),
     # format a setting line from key and value
     mkKeyValue    ? mkKeyValueDefault {} "=",
     # allow lists as values for duplicate keys
@@ -195,12 +238,11 @@ rec {
    *>   name = "edolstra"
    */
   toGitINI = attrs:
-    with builtins;
     let
       mkSectionName = name:
         let
-          containsQuote = libStr.hasInfix ''"'' name;
-          sections = libStr.splitString "." name;
+          containsQuote = hasInfix ''"'' name;
+          sections = splitString "." name;
           section = head sections;
           subsections = tail sections;
           subsection = concatStringsSep "." subsections;
@@ -220,19 +262,19 @@ rec {
       # generation for multiple ini values
       mkKeyValue = k: v:
         let mkKeyValue = mkKeyValueDefault { inherit mkValueString; } " = " k;
-        in concatStringsSep "\n" (map (kv: "\t" + mkKeyValue kv) (lib.toList v));
+        in concatStringsSep "\n" (map (kv: "\t" + mkKeyValue kv) (toList v));
 
       # converts { a.b.c = 5; } to { "a.b".c = 5; } for toINI
       gitFlattenAttrs = let
         recurse = path: value:
-          if isAttrs value && !lib.isDerivation value then
-            lib.mapAttrsToList (name: value: recurse ([ name ] ++ path) value) value
+          if isAttrs value && !isDerivation value then
+            mapAttrsToList (name: value: recurse ([ name ] ++ path) value) value
           else if length path > 1 then {
-            ${concatStringsSep "." (lib.reverseList (tail path))}.${head path} = value;
+            ${concatStringsSep "." (reverseList (tail path))}.${head path} = value;
           } else {
             ${head path} = value;
           };
-      in attrs: lib.foldl lib.recursiveUpdate { } (lib.flatten (recurse [ ] attrs));
+      in attrs: foldl recursiveUpdate { } (flatten (recurse [ ] attrs));
 
       toINI_ = toINI { inherit mkKeyValue mkSectionName; };
     in
@@ -240,25 +282,12 @@ rec {
 
   # mkKeyValueDefault wrapper that handles dconf INI quirks.
   # The main differences of the format is that it requires strings to be quoted.
-  mkDconfKeyValue = mkKeyValueDefault { mkValueString = v: toString (lib.gvariant.mkValue v); } "=";
+  mkDconfKeyValue = mkKeyValueDefault { mkValueString = v: toString (gvariant.mkValue v); } "=";
 
   # Generates INI in dconf keyfile style. See https://help.gnome.org/admin/system-admin-guide/stable/dconf-keyfiles.html.en
   # for details.
   toDconfINI = toINI { mkKeyValue = mkDconfKeyValue; };
 
-  /* Generates JSON from an arbitrary (non-function) value.
-    * For more information see the documentation of the builtin.
-    */
-  toJSON = {}: builtins.toJSON;
-
-
-  /* YAML has been a strict superset of JSON since 1.2, so we
-    * use toJSON. Before it only had a few differences referring
-    * to implicit typing rules, so it should work with older
-    * parsers as well.
-    */
-  toYAML = toJSON;
-
   withRecursion =
     {
       /* If this option is not null, the given value will stop evaluating at a certain depth */
@@ -266,7 +295,7 @@ rec {
       /* If this option is true, an error will be thrown, if a certain given depth is exceeded */
     , throwOnDepthLimit ? true
     }:
-      assert builtins.isInt depthLimit;
+      assert isInt depthLimit;
       let
         specialAttrs = [
           "__functor"
@@ -275,7 +304,7 @@ rec {
           "__pretty"
         ];
         stepIntoAttr = evalNext: name:
-          if builtins.elem name specialAttrs
+          if elem name specialAttrs
             then id
             else evalNext;
         transform = depth:
@@ -284,7 +313,7 @@ rec {
               then throw "Exceeded maximum eval-depth limit of ${toString depthLimit} while trying to evaluate with `generators.withRecursion'!"
               else const "<unevaluated>"
           else id;
-        mapAny = with builtins; depth: v:
+        mapAny = depth: v:
           let
             evalNext = x: mapAny (depth + 1) (transform (depth + 1) x);
           in
@@ -311,9 +340,8 @@ rec {
     indent ? ""
   }:
     let
-    go = indent: v: with builtins;
-    let     isPath   = v: typeOf v == "path";
-            introSpace = if multiline then "\n${indent}  " else " ";
+    go = indent: v:
+    let     introSpace = if multiline then "\n${indent}  " else " ";
             outroSpace = if multiline then "\n${indent}" else " ";
     in if   isInt      v then toString v
     # toString loses precision on floats, so we use toJSON instead. This isn't perfect
@@ -322,16 +350,16 @@ rec {
     else if isFloat    v then builtins.toJSON v
     else if isString   v then
       let
-        lines = filter (v: ! isList v) (builtins.split "\n" v);
-        escapeSingleline = libStr.escape [ "\\" "\"" "\${" ];
-        escapeMultiline = libStr.replaceStrings [ "\${" "''" ] [ "''\${" "'''" ];
+        lines = filter (v: ! isList v) (split "\n" v);
+        escapeSingleline = escape [ "\\" "\"" "\${" ];
+        escapeMultiline = replaceStrings [ "\${" "''" ] [ "''\${" "'''" ];
         singlelineResult = "\"" + concatStringsSep "\\n" (map escapeSingleline lines) + "\"";
         multilineResult = let
           escapedLines = map escapeMultiline lines;
           # The last line gets a special treatment: if it's empty, '' is on its own line at the "outer"
           # indentation level. Otherwise, '' is appended to the last line.
-          lastLine = lib.last escapedLines;
-        in "''" + introSpace + concatStringsSep introSpace (lib.init escapedLines)
+          lastLine = last escapedLines;
+        in "''" + introSpace + concatStringsSep introSpace (init escapedLines)
                 + (if lastLine == "" then outroSpace else introSpace + lastLine) + "''";
       in
         if multiline && length lines > 1 then multilineResult else singlelineResult
@@ -342,11 +370,11 @@ rec {
     else if isList     v then
       if v == [] then "[ ]"
       else "[" + introSpace
-        + libStr.concatMapStringsSep introSpace (go (indent + "  ")) v
+        + concatMapStringsSep introSpace (go (indent + "  ")) v
         + outroSpace + "]"
     else if isFunction v then
-      let fna = lib.functionArgs v;
-          showFnas = concatStringsSep ", " (libAttr.mapAttrsToList
+      let fna = functionArgs v;
+          showFnas = concatStringsSep ", " (mapAttrsToList
                        (name: hasDefVal: if hasDefVal then name + "?" else name)
                        fna);
       in if fna == {}    then "<function>"
@@ -359,10 +387,10 @@ rec {
       else if v ? type && v.type == "derivation" then
         "<derivation ${v.name or "???"}>"
       else "{" + introSpace
-          + libStr.concatStringsSep introSpace (libAttr.mapAttrsToList
+          + concatStringsSep introSpace (mapAttrsToList
               (name: value:
-                "${libStr.escapeNixIdentifier name} = ${
-                  builtins.addErrorContext "while evaluating an attribute `${name}`"
+                "${escapeNixIdentifier name} = ${
+                  addErrorContext "while evaluating an attribute `${name}`"
                     (go (indent + "  ") value)
                 };") v)
         + outroSpace + "}"
@@ -371,9 +399,7 @@ rec {
 
   # PLIST handling
   toPlist = {}: v: let
-    isFloat = builtins.isFloat or (x: false);
-    isPath = x: builtins.typeOf x == "path";
-    expr = ind: x:  with builtins;
+    expr = ind: x:
       if x == null  then "" else
       if isBool x   then bool ind x else
       if isInt x    then int ind x else
@@ -394,23 +420,23 @@ rec {
 
     indent = ind: expr "\t${ind}";
 
-    item = ind: libStr.concatMapStringsSep "\n" (indent ind);
+    item = ind: concatMapStringsSep "\n" (indent ind);
 
-    list = ind: x: libStr.concatStringsSep "\n" [
+    list = ind: x: concatStringsSep "\n" [
       (literal ind "<array>")
       (item ind x)
       (literal ind "</array>")
     ];
 
-    attrs = ind: x: libStr.concatStringsSep "\n" [
+    attrs = ind: x: concatStringsSep "\n" [
       (literal ind "<dict>")
       (attr ind x)
       (literal ind "</dict>")
     ];
 
     attr = let attrFilter = name: value: name != "_module" && value != null;
-    in ind: x: libStr.concatStringsSep "\n" (lib.flatten (lib.mapAttrsToList
-      (name: value: lib.optionals (attrFilter name value) [
+    in ind: x: concatStringsSep "\n" (flatten (mapAttrsToList
+      (name: value: optionals (attrFilter name value) [
       (key "\t${ind}" name)
       (expr "\t${ind}" value)
     ]) x));
@@ -426,11 +452,10 @@ ${expr "" v}
    * the Natural type.
   */
   toDhall = { }@args: v:
-    with builtins;
-    let concatItems = lib.strings.concatStringsSep ", ";
+    let concatItems = concatStringsSep ", ";
     in if isAttrs v then
       "{ ${
-        concatItems (lib.attrsets.mapAttrsToList
+        concatItems (mapAttrsToList
           (key: value: "${key} = ${toDhall args value}") v)
       } }"
     else if isList v then
@@ -444,7 +469,7 @@ ${expr "" v}
     else if v == null then
       abort "generators.toDhall: cannot convert a null to Dhall"
     else
-      builtins.toJSON v;
+      toJSON v;
 
   /*
    Translate a simple Nix expression to Lua representation with occasional
@@ -488,7 +513,6 @@ ${expr "" v}
     /* Interpret as variable bindings */
     asBindings ? false,
   }@args: v:
-    with builtins;
     let
       innerIndent = "${indent}  ";
       introSpace = if multiline then "\n${innerIndent}" else " ";
@@ -501,9 +525,9 @@ ${expr "" v}
       isLuaInline = { _type ? null, ... }: _type == "lua-inline";
 
       generatedBindings =
-          assert lib.assertMsg (badVarNames == []) "Bad Lua var names: ${toPretty {} badVarNames}";
-          libStr.concatStrings (
-            lib.attrsets.mapAttrsToList (key: value: "${indent}${key} = ${toLua innerArgs value}\n") v
+          assert assertMsg (badVarNames == []) "Bad Lua var names: ${toPretty {} badVarNames}";
+          concatStrings (
+            mapAttrsToList (key: value: "${indent}${key} = ${toLua innerArgs value}\n") v
             );
 
       # https://en.wikibooks.org/wiki/Lua_Programming/variable#Variable_names
@@ -515,7 +539,7 @@ ${expr "" v}
     else if v == null then
       "nil"
     else if isInt v || isFloat v || isString v || isBool v then
-      builtins.toJSON v
+      toJSON v
     else if isList v then
       (if v == [ ] then "{}" else
       "{${introSpace}${concatItems (map (value: "${toLua innerArgs value}") v)}${outroSpace}}")
@@ -525,11 +549,11 @@ ${expr "" v}
           "(${v.expr})"
         else if v == { } then
           "{}"
-        else if libAttr.isDerivation v then
+        else if isDerivation v then
           ''"${toString v}"''
         else
           "{${introSpace}${concatItems (
-            lib.attrsets.mapAttrsToList (key: value: "[${builtins.toJSON key}] = ${toLua innerArgs value}") v
+            mapAttrsToList (key: value: "[${toJSON key}] = ${toLua innerArgs value}") v
             )}${outroSpace}}"
       )
     else
@@ -542,4 +566,37 @@ ${expr "" v}
      mkLuaInline :: String -> AttrSet
   */
   mkLuaInline = expr: { _type = "lua-inline"; inherit expr; };
+
+in
+
+# Everything in this attrset is the public interface of the file.
+{
+  inherit
+    mkDconfKeyValue
+    mkKeyValueDefault
+    mkLuaInline
+    mkValueStringDefault
+    toDconfINI
+    toDhall
+    toGitINI
+    toINI
+    toINIWithGlobalSection
+    toKeyValue
+    toLua
+    toPlist
+    toPretty
+    withRecursion
+    ;
+
+  /* Generates JSON from an arbitrary (non-function) value.
+    * For more information see the documentation of the builtin.
+    */
+  toJSON = {}: toJSON;
+
+  /* YAML has been a strict superset of JSON since 1.2, so we
+    * use toJSON. Before it only had a few differences referring
+    * to implicit typing rules, so it should work with older
+    * parsers as well.
+    */
+  toYAML = {}: toJSON;
 }
diff --git a/nixpkgs/lib/kernel.nix b/nixpkgs/lib/kernel.nix
index 33da9663a8ed..7391f9e5d079 100644
--- a/nixpkgs/lib/kernel.nix
+++ b/nixpkgs/lib/kernel.nix
@@ -1,6 +1,8 @@
 { lib }:
 
-with lib;
+let
+  inherit (lib) mkIf versionAtLeast versionOlder;
+in
 {
 
 
diff --git a/nixpkgs/lib/licenses.nix b/nixpkgs/lib/licenses.nix
index 30ca31ff71f2..4cda7e5c01a3 100644
--- a/nixpkgs/lib/licenses.nix
+++ b/nixpkgs/lib/licenses.nix
@@ -599,6 +599,11 @@ in mkLicense lset) ({
     url = "https://fedoraproject.org/wiki/Licensing/GPL_Classpath_Exception";
   };
 
+  giftware = {
+    spdxId = "Giftware";
+    fullName = "Giftware License";
+  };
+
   hpnd = {
     spdxId = "HPND";
     fullName = "Historic Permission Notice and Disclaimer";
@@ -609,6 +614,11 @@ in mkLicense lset) ({
     spdxId = "HPND-sell-variant";
   };
 
+  hpndUc = {
+    spdxId = "HPND-UC";
+    fullName = "Historical Permission Notice and Disclaimer - University of California variant";
+  };
+
   # Intel's license, seems free
   iasl = {
     spdxId = "Intel-ACPI";
@@ -894,6 +904,11 @@ in mkLicense lset) ({
     url = "https://raw.githubusercontent.com/netdata/netdata/master/web/gui/v2/LICENSE.md";
   };
 
+  nistSoftware = {
+    spdxId = "NIST-Software";
+    fullName = "NIST Software License";
+  };
+
   nlpl = {
     spdxId = "NLPL";
     fullName = "No Limit Public License";
@@ -1251,11 +1266,6 @@ in mkLicense lset) ({
   };
 } // {
   # TODO: remove legacy aliases
-  agpl3 = {
-    spdxId = "AGPL-3.0";
-    fullName = "GNU Affero General Public License v3.0";
-    deprecated = true;
-  };
   gpl2 = {
     spdxId = "GPL-2.0";
     fullName = "GNU General Public License v2.0";
diff --git a/nixpkgs/lib/lists.nix b/nixpkgs/lib/lists.nix
index 05216c1a66eb..c162f921280d 100644
--- a/nixpkgs/lib/lists.nix
+++ b/nixpkgs/lib/lists.nix
@@ -1,4 +1,6 @@
-/* General list operations. */
+/**
+  General list operations.
+*/
 { lib }:
 let
   inherit (lib.strings) toInt;
@@ -9,45 +11,112 @@ rec {
 
   inherit (builtins) head tail length isList elemAt concatLists filter elem genList map;
 
-  /*  Create a list consisting of a single element.  `singleton x` is
-      sometimes more convenient with respect to indentation than `[x]`
-      when x spans multiple lines.
+  /**
+    Create a list consisting of a single element. `singleton x` is
+    sometimes more convenient with respect to indentation than `[x]`
+    when x spans multiple lines.
 
-      Type: singleton :: a -> [a]
+    # Inputs
 
-      Example:
-        singleton "foo"
-        => [ "foo" ]
+    `x`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    singleton :: a -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.singleton` usage example
+
+    ```nix
+    singleton "foo"
+    => [ "foo" ]
+    ```
+
+    :::
   */
   singleton = x: [x];
 
-  /*  Apply the function to each element in the list. Same as `map`, but arguments
-      flipped.
+  /**
+    Apply the function to each element in the list.
+    Same as `map`, but arguments flipped.
+
+    # Inputs
+
+    `xs`
+
+    : 1\. Function argument
+
+    `f`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    forEach :: [a] -> (a -> b) -> [b]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.forEach` usage example
 
-      Type: forEach :: [a] -> (a -> b) -> [b]
+    ```nix
+    forEach [ 1 2 ] (x:
+      toString x
+    )
+    => [ "1" "2" ]
+    ```
 
-      Example:
-        forEach [ 1 2 ] (x:
-          toString x
-        )
-        => [ "1" "2" ]
+    :::
   */
   forEach = xs: f: map f xs;
 
-  /* “right fold” a binary function `op` between successive elements of
-     `list` with `nul` as the starting value, i.e.,
-     `foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))`.
+  /**
+    “right fold” a binary function `op` between successive elements of
+    `list` with `nul` as the starting value, i.e.,
+    `foldr op nul [x_1 x_2 ... x_n] == op x_1 (op x_2 ... (op x_n nul))`.
+
+
+    # Inputs
+
+    `op`
+
+    : 1\. Function argument
+
+    `nul`
 
-     Type: foldr :: (a -> b -> b) -> b -> [a] -> b
+    : 2\. Function argument
 
-     Example:
-       concat = foldr (a: b: a + b) "z"
-       concat [ "a" "b" "c" ]
-       => "abcz"
-       # different types
-       strange = foldr (int: str: toString (int + 1) + str) "a"
-       strange [ 1 2 3 4 ]
-       => "2345a"
+    `list`
+
+    : 3\. Function argument
+
+    # Type
+
+    ```
+    foldr :: (a -> b -> b) -> b -> [a] -> b
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.foldr` usage example
+
+    ```nix
+    concat = foldr (a: b: a + b) "z"
+    concat [ "a" "b" "c" ]
+    => "abcz"
+    # different types
+    strange = foldr (int: str: toString (int + 1) + str) "a"
+    strange [ 1 2 3 4 ]
+    => "2345a"
+    ```
+
+    :::
   */
   foldr = op: nul: list:
     let
@@ -58,24 +127,53 @@ rec {
         else op (elemAt list n) (fold' (n + 1));
     in fold' 0;
 
-  /* `fold` is an alias of `foldr` for historic reasons */
+  /**
+    `fold` is an alias of `foldr` for historic reasons
+  */
   # FIXME(Profpatsch): deprecate?
   fold = foldr;
 
 
-  /* “left fold”, like `foldr`, but from the left:
-     `foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`.
+  /**
+    “left fold”, like `foldr`, but from the left:
+
+    `foldl op nul [x_1 x_2 ... x_n] == op (... (op (op nul x_1) x_2) ... x_n)`.
+
+    # Inputs
+
+    `op`
+
+    : 1\. Function argument
+
+    `nul`
+
+    : 2\. Function argument
+
+    `list`
 
-     Type: foldl :: (b -> a -> b) -> b -> [a] -> b
+    : 3\. Function argument
 
-     Example:
-       lconcat = foldl (a: b: a + b) "z"
-       lconcat [ "a" "b" "c" ]
-       => "zabc"
-       # different types
-       lstrange = foldl (str: int: str + toString (int + 1)) "a"
-       lstrange [ 1 2 3 4 ]
-       => "a2345"
+    # Type
+
+    ```
+    foldl :: (b -> a -> b) -> b -> [a] -> b
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.foldl` usage example
+
+    ```nix
+    lconcat = foldl (a: b: a + b) "z"
+    lconcat [ "a" "b" "c" ]
+    => "zabc"
+    # different types
+    lstrange = foldl (str: int: str + toString (int + 1)) "a"
+    lstrange [ 1 2 3 4 ]
+    => "a2345"
+    ```
+
+    :::
   */
   foldl = op: nul: list:
     let
@@ -85,7 +183,7 @@ rec {
         else op (foldl' (n - 1)) (elemAt list n);
     in foldl' (length list - 1);
 
-  /*
+  /**
     Reduce a list by applying a binary operator from left to right,
     starting with an initial accumulator.
 
@@ -119,131 +217,305 @@ rec {
     op (op (... (op (op (op acc₀ x₀) x₁) x₂) ...) xₙ₋₁) xₙ
     ```
 
-    Type: foldl' :: (acc -> x -> acc) -> acc -> [x] -> acc
+    # Inputs
 
-    Example:
-      foldl' (acc: x: acc + x) 0 [1 2 3]
-      => 6
-  */
-  foldl' =
-    /* The binary operation to run, where the two arguments are:
+    `op`
+
+    : The binary operation to run, where the two arguments are:
 
     1. `acc`: The current accumulator value: Either the initial one for the first iteration, or the result of the previous iteration
     2. `x`: The corresponding list element for this iteration
-    */
+
+    `acc`
+
+    : The initial accumulator value.
+
+      The accumulator value is evaluated in any case before the first iteration starts.
+
+      To avoid evaluation even before the `list` argument is given an eta expansion can be used:
+
+      ```nix
+      list: lib.foldl' op acc list
+      ```
+
+    `list`
+
+    : The list to fold
+
+    # Type
+
+    ```
+    foldl' :: (acc -> x -> acc) -> acc -> [x] -> acc
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.foldl'` usage example
+
+    ```nix
+    foldl' (acc: x: acc + x) 0 [1 2 3]
+    => 6
+    ```
+
+    :::
+  */
+  foldl' =
     op:
-    # The initial accumulator value
     acc:
-    # The list to fold
-    list:
-
     # The builtin `foldl'` is a bit lazier than one might expect.
     # See https://github.com/NixOS/nix/pull/7158.
     # In particular, the initial accumulator value is not forced before the first iteration starts.
     builtins.seq acc
-      (builtins.foldl' op acc list);
+      (builtins.foldl' op acc);
+
+  /**
+    Map with index starting from 0
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
 
-  /* Map with index starting from 0
+    `list`
 
-     Type: imap0 :: (int -> a -> b) -> [a] -> [b]
+    : 2\. Function argument
 
-     Example:
-       imap0 (i: v: "${v}-${toString i}") ["a" "b"]
-       => [ "a-0" "b-1" ]
+    # Type
+
+    ```
+    imap0 :: (int -> a -> b) -> [a] -> [b]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.imap0` usage example
+
+    ```nix
+    imap0 (i: v: "${v}-${toString i}") ["a" "b"]
+    => [ "a-0" "b-1" ]
+    ```
+
+    :::
   */
   imap0 = f: list: genList (n: f n (elemAt list n)) (length list);
 
-  /* Map with index starting from 1
+  /**
+    Map with index starting from 1
+
 
-     Type: imap1 :: (int -> a -> b) -> [a] -> [b]
+    # Inputs
 
-     Example:
-       imap1 (i: v: "${v}-${toString i}") ["a" "b"]
-       => [ "a-1" "b-2" ]
+    `f`
+
+    : 1\. Function argument
+
+    `list`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    imap1 :: (int -> a -> b) -> [a] -> [b]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.imap1` usage example
+
+    ```nix
+    imap1 (i: v: "${v}-${toString i}") ["a" "b"]
+    => [ "a-1" "b-2" ]
+    ```
+
+    :::
   */
   imap1 = f: list: genList (n: f (n + 1) (elemAt list n)) (length list);
 
-  /* Map and concatenate the result.
+  /**
+    Map and concatenate the result.
+
+    # Type
+
+    ```
+    concatMap :: (a -> [b]) -> [a] -> [b]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.concatMap` usage example
 
-     Type: concatMap :: (a -> [b]) -> [a] -> [b]
+    ```nix
+    concatMap (x: [x] ++ ["z"]) ["a" "b"]
+    => [ "a" "z" "b" "z" ]
+    ```
 
-     Example:
-       concatMap (x: [x] ++ ["z"]) ["a" "b"]
-       => [ "a" "z" "b" "z" ]
+    :::
   */
   concatMap = builtins.concatMap;
 
-  /* Flatten the argument into a single list; that is, nested lists are
-     spliced into the top-level lists.
+  /**
+    Flatten the argument into a single list; that is, nested lists are
+    spliced into the top-level lists.
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.flatten` usage example
+
+    ```nix
+    flatten [1 [2 [3] 4] 5]
+    => [1 2 3 4 5]
+    flatten 1
+    => [1]
+    ```
 
-     Example:
-       flatten [1 [2 [3] 4] 5]
-       => [1 2 3 4 5]
-       flatten 1
-       => [1]
+    :::
   */
   flatten = x:
     if isList x
     then concatMap (y: flatten y) x
     else [x];
 
-  /* Remove elements equal to 'e' from a list.  Useful for buildInputs.
+  /**
+    Remove elements equal to 'e' from a list.  Useful for buildInputs.
+
+
+    # Inputs
+
+    `e`
 
-     Type: remove :: a -> [a] -> [a]
+    : Element to remove from `list`
 
-     Example:
-       remove 3 [ 1 3 4 3 ]
-       => [ 1 4 ]
+    `list`
+
+    : The list
+
+    # Type
+
+    ```
+    remove :: a -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.remove` usage example
+
+    ```nix
+    remove 3 [ 1 3 4 3 ]
+    => [ 1 4 ]
+    ```
+
+    :::
   */
   remove =
-    # Element to remove from the list
     e: filter (x: x != e);
 
-  /* Find the sole element in the list matching the specified
-     predicate, returns `default` if no such element exists, or
-     `multiple` if there are multiple matching elements.
+  /**
+    Find the sole element in the list matching the specified
+    predicate.
+
+    Returns `default` if no such element exists, or
+    `multiple` if there are multiple matching elements.
+
+
+    # Inputs
+
+    `pred`
+
+    : Predicate
+
+    `default`
+
+    : Default value to return if element was not found.
+
+    `multiple`
+
+    : Default value to return if more than one element was found
+
+    `list`
+
+    : Input list
 
-     Type: findSingle :: (a -> bool) -> a -> a -> [a] -> a
+    # Type
 
-     Example:
-       findSingle (x: x == 3) "none" "multiple" [ 1 3 3 ]
-       => "multiple"
-       findSingle (x: x == 3) "none" "multiple" [ 1 3 ]
-       => 3
-       findSingle (x: x == 3) "none" "multiple" [ 1 9 ]
-       => "none"
+    ```
+    findSingle :: (a -> bool) -> a -> a -> [a] -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.findSingle` usage example
+
+    ```nix
+    findSingle (x: x == 3) "none" "multiple" [ 1 3 3 ]
+    => "multiple"
+    findSingle (x: x == 3) "none" "multiple" [ 1 3 ]
+    => 3
+    findSingle (x: x == 3) "none" "multiple" [ 1 9 ]
+    => "none"
+    ```
+
+    :::
   */
   findSingle =
-    # Predicate
     pred:
-    # Default value to return if element was not found.
     default:
-    # Default value to return if more than one element was found
     multiple:
-    # Input list
     list:
     let found = filter pred list; len = length found;
     in if len == 0 then default
       else if len != 1 then multiple
       else head found;
 
-  /* Find the first index in the list matching the specified
-     predicate or return `default` if no such element exists.
+  /**
+    Find the first index in the list matching the specified
+    predicate or return `default` if no such element exists.
+
+    # Inputs
+
+    `pred`
+
+    : Predicate
+
+    `default`
+
+    : Default value to return
+
+    `list`
+
+    : Input list
+
+    # Type
+
+    ```
+    findFirstIndex :: (a -> Bool) -> b -> [a] -> (Int | b)
+    ```
 
-     Type: findFirstIndex :: (a -> Bool) -> b -> [a] -> (Int | b)
+    # Examples
+    :::{.example}
+    ## `lib.lists.findFirstIndex` usage example
 
-     Example:
-       findFirstIndex (x: x > 3) null [ 0 6 4 ]
-       => 1
-       findFirstIndex (x: x > 9) null [ 0 6 4 ]
-       => null
+    ```nix
+    findFirstIndex (x: x > 3) null [ 0 6 4 ]
+    => 1
+    findFirstIndex (x: x > 9) null [ 0 6 4 ]
+    => null
+    ```
+
+    :::
   */
   findFirstIndex =
-    # Predicate
     pred:
-    # Default value to return
     default:
-    # Input list
     list:
     let
       # A naive recursive implementation would be much simpler, but
@@ -278,23 +550,46 @@ rec {
     else
       resultIndex;
 
-  /* Find the first element in the list matching the specified
-     predicate or return `default` if no such element exists.
+  /**
+    Find the first element in the list matching the specified
+    predicate or return `default` if no such element exists.
+
+    # Inputs
+
+    `pred`
+
+    : Predicate
+
+    `default`
+
+    : Default value to return
+
+    `list`
 
-     Type: findFirst :: (a -> bool) -> a -> [a] -> a
+    : Input list
+
+    # Type
+
+    ```
+    findFirst :: (a -> bool) -> a -> [a] -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.findFirst` usage example
+
+    ```nix
+    findFirst (x: x > 3) 7 [ 1 6 4 ]
+    => 6
+    findFirst (x: x > 9) 7 [ 1 6 4 ]
+    => 7
+    ```
 
-     Example:
-       findFirst (x: x > 3) 7 [ 1 6 4 ]
-       => 6
-       findFirst (x: x > 9) 7 [ 1 6 4 ]
-       => 7
+    :::
   */
   findFirst =
-    # Predicate
     pred:
-    # Default value to return
     default:
-    # Input list
     list:
     let
       index = findFirstIndex pred null list;
@@ -304,152 +599,359 @@ rec {
     else
       elemAt list index;
 
-  /* Return true if function `pred` returns true for at least one
-     element of `list`.
+  /**
+    Return true if function `pred` returns true for at least one
+    element of `list`.
 
-     Type: any :: (a -> bool) -> [a] -> bool
+    # Inputs
 
-     Example:
-       any isString [ 1 "a" { } ]
-       => true
-       any isString [ 1 { } ]
-       => false
+    `pred`
+
+    : Predicate
+
+    `list`
+
+    : Input list
+
+    # Type
+
+    ```
+    any :: (a -> bool) -> [a] -> bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.any` usage example
+
+    ```nix
+    any isString [ 1 "a" { } ]
+    => true
+    any isString [ 1 { } ]
+    => false
+    ```
+
+    :::
   */
   any = builtins.any;
 
-  /* Return true if function `pred` returns true for all elements of
-     `list`.
+  /**
+    Return true if function `pred` returns true for all elements of
+    `list`.
+
+    # Inputs
+
+    `pred`
+
+    : Predicate
+
+    `list`
 
-     Type: all :: (a -> bool) -> [a] -> bool
+    : Input list
 
-     Example:
-       all (x: x < 3) [ 1 2 ]
-       => true
-       all (x: x < 3) [ 1 2 3 ]
-       => false
+    # Type
+
+    ```
+    all :: (a -> bool) -> [a] -> bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.all` usage example
+
+    ```nix
+    all (x: x < 3) [ 1 2 ]
+    => true
+    all (x: x < 3) [ 1 2 3 ]
+    => false
+    ```
+
+    :::
   */
   all = builtins.all;
 
-  /* Count how many elements of `list` match the supplied predicate
-     function.
+  /**
+    Count how many elements of `list` match the supplied predicate
+    function.
+
+    # Inputs
+
+    `pred`
+
+    : Predicate
+
+    # Type
+
+    ```
+    count :: (a -> bool) -> [a] -> int
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.count` usage example
 
-     Type: count :: (a -> bool) -> [a] -> int
+    ```nix
+    count (x: x == 3) [ 3 2 3 4 6 ]
+    => 2
+    ```
 
-     Example:
-       count (x: x == 3) [ 3 2 3 4 6 ]
-       => 2
+    :::
   */
   count =
-    # Predicate
     pred: foldl' (c: x: if pred x then c + 1 else c) 0;
 
-  /* Return a singleton list or an empty list, depending on a boolean
-     value.  Useful when building lists with optional elements
-     (e.g. `++ optional (system == "i686-linux") firefox`).
+  /**
+    Return a singleton list or an empty list, depending on a boolean
+    value.  Useful when building lists with optional elements
+    (e.g. `++ optional (system == "i686-linux") firefox`).
+
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
+
+    `elem`
+
+    : 2\. Function argument
+
+    # Type
 
-     Type: optional :: bool -> a -> [a]
+    ```
+    optional :: bool -> a -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.optional` usage example
 
-     Example:
-       optional true "foo"
-       => [ "foo" ]
-       optional false "foo"
-       => [ ]
+    ```nix
+    optional true "foo"
+    => [ "foo" ]
+    optional false "foo"
+    => [ ]
+    ```
+
+    :::
   */
   optional = cond: elem: if cond then [elem] else [];
 
-  /* Return a list or an empty list, depending on a boolean value.
+  /**
+    Return a list or an empty list, depending on a boolean value.
+
+    # Inputs
+
+    `cond`
 
-     Type: optionals :: bool -> [a] -> [a]
+    : Condition
 
-     Example:
-       optionals true [ 2 3 ]
-       => [ 2 3 ]
-       optionals false [ 2 3 ]
-       => [ ]
+    `elems`
+
+    : List to return if condition is true
+
+    # Type
+
+    ```
+    optionals :: bool -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.optionals` usage example
+
+    ```nix
+    optionals true [ 2 3 ]
+    => [ 2 3 ]
+    optionals false [ 2 3 ]
+    => [ ]
+    ```
+
+    :::
   */
   optionals =
-    # Condition
     cond:
-    # List to return if condition is true
     elems: if cond then elems else [];
 
 
-  /* If argument is a list, return it; else, wrap it in a singleton
-     list.  If you're using this, you should almost certainly
-     reconsider if there isn't a more "well-typed" approach.
+  /**
+    If argument is a list, return it; else, wrap it in a singleton
+    list. If you're using this, you should almost certainly
+    reconsider if there isn't a more "well-typed" approach.
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.toList` usage example
+
+    ```nix
+    toList [ 1 2 ]
+    => [ 1 2 ]
+    toList "hi"
+    => [ "hi "]
+    ```
 
-     Example:
-       toList [ 1 2 ]
-       => [ 1 2 ]
-       toList "hi"
-       => [ "hi "]
+    :::
   */
   toList = x: if isList x then x else [x];
 
-  /* Return a list of integers from `first` up to and including `last`.
+  /**
+    Return a list of integers from `first` up to and including `last`.
+
+    # Inputs
+
+    `first`
+
+    : First integer in the range
+
+    `last`
+
+    : Last integer in the range
+
+    # Type
+
+    ```
+    range :: int -> int -> [int]
+    ```
 
-     Type: range :: int -> int -> [int]
+    # Examples
+    :::{.example}
+    ## `lib.lists.range` usage example
 
-     Example:
-       range 2 4
-       => [ 2 3 4 ]
-       range 3 2
-       => [ ]
+    ```nix
+    range 2 4
+    => [ 2 3 4 ]
+    range 3 2
+    => [ ]
+    ```
+
+    :::
   */
   range =
-    # First integer in the range
     first:
-    # Last integer in the range
     last:
     if first > last then
       []
     else
       genList (n: first + n) (last - first + 1);
 
-  /* Return a list with `n` copies of an element.
+  /**
+    Return a list with `n` copies of an element.
+
+    # Inputs
+
+    `n`
+
+    : 1\. Function argument
 
-    Type: replicate :: int -> a -> [a]
+    `elem`
 
-    Example:
-      replicate 3 "a"
-      => [ "a" "a" "a" ]
-      replicate 2 true
-      => [ true true ]
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    replicate :: int -> a -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.replicate` usage example
+
+    ```nix
+    replicate 3 "a"
+    => [ "a" "a" "a" ]
+    replicate 2 true
+    => [ true true ]
+    ```
+
+    :::
   */
   replicate = n: elem: genList (_: elem) n;
 
-  /* Splits the elements of a list in two lists, `right` and
-     `wrong`, depending on the evaluation of a predicate.
+  /**
+    Splits the elements of a list in two lists, `right` and
+    `wrong`, depending on the evaluation of a predicate.
+
+    # Inputs
+
+    `pred`
+
+    : Predicate
+
+    `list`
+
+    : Input list
+
+    # Type
+
+    ```
+    (a -> bool) -> [a] -> { right :: [a]; wrong :: [a]; }
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.partition` usage example
 
-     Type: (a -> bool) -> [a] -> { right :: [a]; wrong :: [a]; }
+    ```nix
+    partition (x: x > 2) [ 5 1 2 3 4 ]
+    => { right = [ 5 3 4 ]; wrong = [ 1 2 ]; }
+    ```
 
-     Example:
-       partition (x: x > 2) [ 5 1 2 3 4 ]
-       => { right = [ 5 3 4 ]; wrong = [ 1 2 ]; }
+    :::
   */
   partition = builtins.partition;
 
-  /* Splits the elements of a list into many lists, using the return value of a predicate.
-     Predicate should return a string which becomes keys of attrset `groupBy` returns.
+  /**
+    Splits the elements of a list into many lists, using the return value of a predicate.
+    Predicate should return a string which becomes keys of attrset `groupBy` returns.
+    `groupBy'` allows to customise the combining function and initial value
+
+    # Inputs
+
+    `op`
+
+    : 1\. Function argument
+
+    `nul`
+
+    : 2\. Function argument
 
-     `groupBy'` allows to customise the combining function and initial value
+    `pred`
 
-     Example:
-       groupBy (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
-       => { true = [ 5 3 4 ]; false = [ 1 2 ]; }
-       groupBy (x: x.name) [ {name = "icewm"; script = "icewm &";}
-                             {name = "xfce";  script = "xfce4-session &";}
-                             {name = "icewm"; script = "icewmbg &";}
-                             {name = "mate";  script = "gnome-session &";}
-                           ]
-       => { icewm = [ { name = "icewm"; script = "icewm &"; }
-                      { name = "icewm"; script = "icewmbg &"; } ];
-            mate  = [ { name = "mate";  script = "gnome-session &"; } ];
-            xfce  = [ { name = "xfce";  script = "xfce4-session &"; } ];
-          }
+    : 3\. Function argument
 
-       groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
-       => { true = 12; false = 3; }
+    `lst`
+
+    : 4\. Function argument
+
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.groupBy'` usage example
+
+    ```nix
+    groupBy (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
+    => { true = [ 5 3 4 ]; false = [ 1 2 ]; }
+    groupBy (x: x.name) [ {name = "icewm"; script = "icewm &";}
+                          {name = "xfce";  script = "xfce4-session &";}
+                          {name = "icewm"; script = "icewmbg &";}
+                          {name = "mate";  script = "gnome-session &";}
+                        ]
+    => { icewm = [ { name = "icewm"; script = "icewm &"; }
+                   { name = "icewm"; script = "icewmbg &"; } ];
+         mate  = [ { name = "mate";  script = "gnome-session &"; } ];
+         xfce  = [ { name = "xfce";  script = "xfce4-session &"; } ];
+       }
+
+    groupBy' builtins.add 0 (x: boolToString (x > 2)) [ 5 1 2 3 4 ]
+    => { true = 12; false = 3; }
+    ```
+
+    :::
   */
   groupBy' = op: nul: pred: lst: mapAttrs (name: foldl op nul) (groupBy pred lst);
 
@@ -461,68 +963,153 @@ rec {
          r // { ${key} = (r.${key} or []) ++ [e]; }
     ) {});
 
-  /* Merges two lists of the same size together. If the sizes aren't the same
-     the merging stops at the shortest. How both lists are merged is defined
-     by the first argument.
+  /**
+    Merges two lists of the same size together. If the sizes aren't the same
+    the merging stops at the shortest. How both lists are merged is defined
+    by the first argument.
+
+    # Inputs
+
+    `f`
 
-     Type: zipListsWith :: (a -> b -> c) -> [a] -> [b] -> [c]
+    : Function to zip elements of both lists
 
-     Example:
-       zipListsWith (a: b: a + b) ["h" "l"] ["e" "o"]
-       => ["he" "lo"]
+    `fst`
+
+    : First list
+
+    `snd`
+
+    : Second list
+
+    # Type
+
+    ```
+    zipListsWith :: (a -> b -> c) -> [a] -> [b] -> [c]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.zipListsWith` usage example
+
+    ```nix
+    zipListsWith (a: b: a + b) ["h" "l"] ["e" "o"]
+    => ["he" "lo"]
+    ```
+
+    :::
   */
   zipListsWith =
-    # Function to zip elements of both lists
     f:
-    # First list
     fst:
-    # Second list
     snd:
     genList
       (n: f (elemAt fst n) (elemAt snd n)) (min (length fst) (length snd));
 
-  /* Merges two lists of the same size together. If the sizes aren't the same
-     the merging stops at the shortest.
+  /**
+    Merges two lists of the same size together. If the sizes aren't the same
+    the merging stops at the shortest.
+
+    # Inputs
+
+    `fst`
 
-     Type: zipLists :: [a] -> [b] -> [{ fst :: a; snd :: b; }]
+    : First list
 
-     Example:
-       zipLists [ 1 2 ] [ "a" "b" ]
-       => [ { fst = 1; snd = "a"; } { fst = 2; snd = "b"; } ]
+    `snd`
+
+    : Second list
+
+    # Type
+
+    ```
+    zipLists :: [a] -> [b] -> [{ fst :: a; snd :: b; }]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.zipLists` usage example
+
+    ```nix
+    zipLists [ 1 2 ] [ "a" "b" ]
+    => [ { fst = 1; snd = "a"; } { fst = 2; snd = "b"; } ]
+    ```
+
+    :::
   */
   zipLists = zipListsWith (fst: snd: { inherit fst snd; });
 
-  /* Reverse the order of the elements of a list.
+  /**
+    Reverse the order of the elements of a list.
+
+    # Inputs
+
+    `xs`
+
+    : 1\. Function argument
 
-     Type: reverseList :: [a] -> [a]
+    # Type
 
-     Example:
+    ```
+    reverseList :: [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.reverseList` usage example
 
-       reverseList [ "b" "o" "j" ]
-       => [ "j" "o" "b" ]
+    ```nix
+    reverseList [ "b" "o" "j" ]
+    => [ "j" "o" "b" ]
+    ```
+
+    :::
   */
   reverseList = xs:
     let l = length xs; in genList (n: elemAt xs (l - n - 1)) l;
 
-  /* Depth-First Search (DFS) for lists `list != []`.
+  /**
+    Depth-First Search (DFS) for lists `list != []`.
+
+    `before a b == true` means that `b` depends on `a` (there's an
+    edge from `b` to `a`).
+
+
+    # Inputs
 
-     `before a b == true` means that `b` depends on `a` (there's an
-     edge from `b` to `a`).
+    `stopOnCycles`
 
-     Example:
-         listDfs true hasPrefix [ "/home/user" "other" "/" "/home" ]
-           == { minimal = "/";                  # minimal element
-                visited = [ "/home/user" ];     # seen elements (in reverse order)
-                rest    = [ "/home" "other" ];  # everything else
-              }
+    : 1\. Function argument
 
-         listDfs true hasPrefix [ "/home/user" "other" "/" "/home" "/" ]
-           == { cycle   = "/";                  # cycle encountered at this element
-                loops   = [ "/" ];              # and continues to these elements
-                visited = [ "/" "/home/user" ]; # elements leading to the cycle (in reverse order)
-                rest    = [ "/home" "other" ];  # everything else
+    `before`
 
-   */
+    : 2\. Function argument
+
+    `list`
+
+    : 3\. Function argument
+
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.listDfs` usage example
+
+    ```nix
+    listDfs true hasPrefix [ "/home/user" "other" "/" "/home" ]
+      == { minimal = "/";                  # minimal element
+           visited = [ "/home/user" ];     # seen elements (in reverse order)
+           rest    = [ "/home" "other" ];  # everything else
+         }
+
+    listDfs true hasPrefix [ "/home/user" "other" "/" "/home" "/" ]
+      == { cycle   = "/";                  # cycle encountered at this element
+           loops   = [ "/" ];              # and continues to these elements
+           visited = [ "/" "/home/user" ]; # elements leading to the cycle (in reverse order)
+           rest    = [ "/home" "other" ];  # everything else
+    ```
+
+    :::
+  */
   listDfs = stopOnCycles: before: list:
     let
       dfs' = us: visited: rest:
@@ -540,28 +1127,46 @@ rec {
                           (tail b.right ++ b.wrong);
     in dfs' (head list) [] (tail list);
 
-  /* Sort a list based on a partial ordering using DFS. This
-     implementation is O(N^2), if your ordering is linear, use `sort`
-     instead.
+  /**
+    Sort a list based on a partial ordering using DFS. This
+    implementation is O(N^2), if your ordering is linear, use `sort`
+    instead.
 
-     `before a b == true` means that `b` should be after `a`
-     in the result.
+    `before a b == true` means that `b` should be after `a`
+    in the result.
 
-     Example:
 
-         toposort hasPrefix [ "/home/user" "other" "/" "/home" ]
-           == { result = [ "/" "/home" "/home/user" "other" ]; }
+    # Inputs
 
-         toposort hasPrefix [ "/home/user" "other" "/" "/home" "/" ]
-           == { cycle = [ "/home/user" "/" "/" ]; # path leading to a cycle
-                loops = [ "/" ]; }                # loops back to these elements
+    `before`
 
-         toposort hasPrefix [ "other" "/home/user" "/home" "/" ]
-           == { result = [ "other" "/" "/home" "/home/user" ]; }
+    : 1\. Function argument
 
-         toposort (a: b: a < b) [ 3 2 1 ] == { result = [ 1 2 3 ]; }
+    `list`
 
-   */
+    : 2\. Function argument
+
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.toposort` usage example
+
+    ```nix
+    toposort hasPrefix [ "/home/user" "other" "/" "/home" ]
+      == { result = [ "/" "/home" "/home/user" "other" ]; }
+
+    toposort hasPrefix [ "/home/user" "other" "/" "/home" "/" ]
+      == { cycle = [ "/home/user" "/" "/" ]; # path leading to a cycle
+           loops = [ "/" ]; }                # loops back to these elements
+
+    toposort hasPrefix [ "other" "/home/user" "/home" "/" ]
+      == { result = [ "other" "/" "/home" "/home/user" ]; }
+
+    toposort (a: b: a < b) [ 3 2 1 ] == { result = [ 1 2 3 ]; }
+    ```
+
+    :::
+  */
   toposort = before: list:
     let
       dfsthis = listDfs true before list;
@@ -581,24 +1186,45 @@ rec {
                 else # there are no cycles
                      { result = [ dfsthis.minimal ] ++ toporest.result; };
 
-  /* Sort a list based on a comparator function which compares two
-     elements and returns true if the first argument is strictly below
-     the second argument.  The returned list is sorted in an increasing
-     order.  The implementation does a quick-sort.
+  /**
+    Sort a list based on a comparator function which compares two
+    elements and returns true if the first argument is strictly below
+    the second argument.  The returned list is sorted in an increasing
+    order.  The implementation does a quick-sort.
+
+    See also [`sortOn`](#function-library-lib.lists.sortOn), which applies the
+    default comparison on a function-derived property, and may be more efficient.
+
+    # Inputs
+
+    `comparator`
+
+    : 1\. Function argument
+
+    `list`
+
+    : 2\. Function argument
+
+    # Type
 
-     See also [`sortOn`](#function-library-lib.lists.sortOn), which applies the
-     default comparison on a function-derived property, and may be more efficient.
+    ```
+    sort :: (a -> a -> Bool) -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.sort` usage example
 
-     Example:
-       sort (p: q: p < q) [ 5 3 7 ]
-       => [ 3 5 7 ]
+    ```nix
+    sort (p: q: p < q) [ 5 3 7 ]
+    => [ 3 5 7 ]
+    ```
 
-     Type:
-       sort :: (a -> a -> Bool) -> [a] -> [a]
+    :::
   */
   sort = builtins.sort;
 
-  /*
+  /**
     Sort a list based on the default comparison of a derived property `b`.
 
     The items are returned in `b`-increasing order.
@@ -614,12 +1240,33 @@ rec {
     sortOn f == sort (p: q: f p < f q)
     ```
 
-    Example:
-      sortOn stringLength [ "aa" "b" "cccc" ]
-      => [ "b" "aa" "cccc" ]
 
-    Type:
-      sortOn :: (a -> b) -> [a] -> [a], for comparable b
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
+
+    `list`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    sortOn :: (a -> b) -> [a] -> [a], for comparable b
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.sortOn` usage example
+
+    ```nix
+    sortOn stringLength [ "aa" "b" "cccc" ]
+    => [ "b" "aa" "cccc" ]
+    ```
+
+    :::
   */
   sortOn = f: list:
     let
@@ -634,17 +1281,40 @@ rec {
           (a: b: head a < head b)
           pairs);
 
-  /* Compare two lists element-by-element.
+  /**
+    Compare two lists element-by-element.
+
+    # Inputs
+
+    `cmp`
+
+    : 1\. Function argument
+
+    `a`
+
+    : 2\. Function argument
+
+    `b`
+
+    : 3\. Function argument
+
 
-     Example:
-       compareLists compare [] []
-       => 0
-       compareLists compare [] [ "a" ]
-       => -1
-       compareLists compare [ "a" ] []
-       => 1
-       compareLists compare [ "a" "b" ] [ "a" "c" ]
-       => -1
+    # Examples
+    :::{.example}
+    ## `lib.lists.compareLists` usage example
+
+    ```nix
+    compareLists compare [] []
+    => 0
+    compareLists compare [] [ "a" ]
+    => -1
+    compareLists compare [ "a" ] []
+    => 1
+    compareLists compare [ "a" "b" ] [ "a" "c" ]
+    => -1
+    ```
+
+    :::
   */
   compareLists = cmp: a: b:
     if a == []
@@ -658,16 +1328,32 @@ rec {
               then compareLists cmp (tail a) (tail b)
               else rel;
 
-  /* Sort list using "Natural sorting".
-     Numeric portions of strings are sorted in numeric order.
+  /**
+    Sort list using "Natural sorting".
+    Numeric portions of strings are sorted in numeric order.
+
+
+    # Inputs
+
+    `lst`
+
+    : 1\. Function argument
+
 
-     Example:
-       naturalSort ["disk11" "disk8" "disk100" "disk9"]
-       => ["disk8" "disk9" "disk11" "disk100"]
-       naturalSort ["10.46.133.149" "10.5.16.62" "10.54.16.25"]
-       => ["10.5.16.62" "10.46.133.149" "10.54.16.25"]
-       naturalSort ["v0.2" "v0.15" "v0.0.9"]
-       => [ "v0.0.9" "v0.2" "v0.15" ]
+    # Examples
+    :::{.example}
+    ## `lib.lists.naturalSort` usage example
+
+    ```nix
+    naturalSort ["disk11" "disk8" "disk100" "disk9"]
+    => ["disk8" "disk9" "disk11" "disk100"]
+    naturalSort ["10.46.133.149" "10.5.16.62" "10.54.16.25"]
+    => ["10.5.16.62" "10.46.133.149" "10.54.16.25"]
+    naturalSort ["v0.2" "v0.15" "v0.0.9"]
+    => [ "v0.0.9" "v0.2" "v0.15" ]
+    ```
+
+    :::
   */
   naturalSort = lst:
     let
@@ -677,61 +1363,149 @@ rec {
     in
       map (x: elemAt x 1) (sort less prepared);
 
-  /* Return the first (at most) N elements of a list.
+  /**
+    Return the first (at most) N elements of a list.
+
+
+    # Inputs
+
+    `count`
+
+    : Number of elements to take
+
+    `list`
 
-     Type: take :: int -> [a] -> [a]
+    : Input list
 
-     Example:
-       take 2 [ "a" "b" "c" "d" ]
-       => [ "a" "b" ]
-       take 2 [ ]
-       => [ ]
+    # Type
+
+    ```
+    take :: int -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.take` usage example
+
+    ```nix
+    take 2 [ "a" "b" "c" "d" ]
+    => [ "a" "b" ]
+    take 2 [ ]
+    => [ ]
+    ```
+
+    :::
   */
   take =
-    # Number of elements to take
     count: sublist 0 count;
 
-  /* Remove the first (at most) N elements of a list.
+  /**
+    Remove the first (at most) N elements of a list.
 
-     Type: drop :: int -> [a] -> [a]
 
-     Example:
-       drop 2 [ "a" "b" "c" "d" ]
-       => [ "c" "d" ]
-       drop 2 [ ]
-       => [ ]
+    # Inputs
+
+    `count`
+
+    : Number of elements to drop
+
+    `list`
+
+    : Input list
+
+    # Type
+
+    ```
+    drop :: int -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.drop` usage example
+
+    ```nix
+    drop 2 [ "a" "b" "c" "d" ]
+    => [ "c" "d" ]
+    drop 2 [ ]
+    => [ ]
+    ```
+
+    :::
   */
   drop =
-    # Number of elements to drop
     count:
-    # Input list
     list: sublist count (length list) list;
 
-  /* Whether the first list is a prefix of the second list.
+  /**
+    Whether the first list is a prefix of the second list.
+
+
+    # Inputs
+
+    `list1`
 
-  Type: hasPrefix :: [a] -> [a] -> bool
+    : 1\. Function argument
 
-  Example:
+    `list2`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    hasPrefix :: [a] -> [a] -> bool
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.hasPrefix` usage example
+
+    ```nix
     hasPrefix [ 1 2 ] [ 1 2 3 4 ]
     => true
     hasPrefix [ 0 1 ] [ 1 2 3 4 ]
     => false
+    ```
+
+    :::
   */
   hasPrefix =
     list1:
     list2:
     take (length list1) list2 == list1;
 
-  /* Remove the first list as a prefix from the second list.
-  Error if the first list isn't a prefix of the second list.
+  /**
+    Remove the first list as a prefix from the second list.
+    Error if the first list isn't a prefix of the second list.
+
+    # Inputs
+
+    `list1`
+
+    : 1\. Function argument
+
+    `list2`
 
-  Type: removePrefix :: [a] -> [a] -> [a]
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    removePrefix :: [a] -> [a] -> [a]
+    ```
 
-  Example:
+    # Examples
+    :::{.example}
+    ## `lib.lists.removePrefix` usage example
+
+    ```nix
     removePrefix [ 1 2 ] [ 1 2 3 4 ]
     => [ 3 4 ]
     removePrefix [ 0 1 ] [ 1 2 3 4 ]
     => <error>
+    ```
+
+    :::
   */
   removePrefix =
     list1:
@@ -741,23 +1515,46 @@ rec {
     else
       throw "lib.lists.removePrefix: First argument is not a list prefix of the second argument";
 
-  /* Return a list consisting of at most `count` elements of `list`,
-     starting at index `start`.
+  /**
+    Return a list consisting of at most `count` elements of `list`,
+    starting at index `start`.
+
+    # Inputs
+
+    `start`
+
+    : Index at which to start the sublist
+
+    `count`
 
-     Type: sublist :: int -> int -> [a] -> [a]
+    : Number of elements to take
 
-     Example:
-       sublist 1 3 [ "a" "b" "c" "d" "e" ]
-       => [ "b" "c" "d" ]
-       sublist 1 3 [ ]
-       => [ ]
+    `list`
+
+    : Input list
+
+    # Type
+
+    ```
+    sublist :: int -> int -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.sublist` usage example
+
+    ```nix
+    sublist 1 3 [ "a" "b" "c" "d" "e" ]
+    => [ "b" "c" "d" ]
+    sublist 1 3 [ ]
+    => [ ]
+    ```
+
+    :::
   */
   sublist =
-    # Index at which to start the sublist
     start:
-    # Number of elements to take
     count:
-    # Input list
     list:
     let len = length list; in
     genList
@@ -766,17 +1563,40 @@ rec {
        else if start + count > len then len - start
        else count);
 
-  /* The common prefix of two lists.
+  /**
+    The common prefix of two lists.
+
+
+    # Inputs
+
+    `list1`
 
-  Type: commonPrefix :: [a] -> [a] -> [a]
+    : 1\. Function argument
 
-  Example:
+    `list2`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    commonPrefix :: [a] -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.commonPrefix` usage example
+
+    ```nix
     commonPrefix [ 1 2 3 4 5 6 ] [ 1 2 4 8 ]
     => [ 1 2 ]
     commonPrefix [ 1 2 3 ] [ 1 2 3 4 5 ]
     => [ 1 2 3 ]
     commonPrefix [ 1 2 3 ] [ 4 5 6 ]
     => [ ]
+    ```
+
+    :::
   */
   commonPrefix =
     list1:
@@ -792,87 +1612,225 @@ rec {
     in
     take commonPrefixLength list1;
 
-  /* Return the last element of a list.
+  /**
+    Return the last element of a list.
+
+    This function throws an error if the list is empty.
+
+
+    # Inputs
 
-     This function throws an error if the list is empty.
+    `list`
 
-     Type: last :: [a] -> a
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    last :: [a] -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.last` usage example
+
+    ```nix
+    last [ 1 2 3 ]
+    => 3
+    ```
 
-     Example:
-       last [ 1 2 3 ]
-       => 3
+    :::
   */
   last = list:
     assert lib.assertMsg (list != []) "lists.last: list must not be empty!";
     elemAt list (length list - 1);
 
-  /* Return all elements but the last.
+  /**
+    Return all elements but the last.
 
-     This function throws an error if the list is empty.
+    This function throws an error if the list is empty.
 
-     Type: init :: [a] -> [a]
 
-     Example:
-       init [ 1 2 3 ]
-       => [ 1 2 ]
+    # Inputs
+
+    `list`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    init :: [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.init` usage example
+
+    ```nix
+    init [ 1 2 3 ]
+    => [ 1 2 ]
+    ```
+
+    :::
   */
   init = list:
     assert lib.assertMsg (list != []) "lists.init: list must not be empty!";
     take (length list - 1) list;
 
 
-  /* Return the image of the cross product of some lists by a function.
+  /**
+    Return the image of the cross product of some lists by a function.
+
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.crossLists` usage example
 
-    Example:
-      crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
-      => [ "13" "14" "23" "24" ]
+    ```nix
+    crossLists (x:y: "${toString x}${toString y}") [[1 2] [3 4]]
+    => [ "13" "14" "23" "24" ]
+    ```
+
+    :::
   */
   crossLists = warn
     "lib.crossLists is deprecated, use lib.cartesianProductOfSets instead."
     (f: foldl (fs: args: concatMap (f: map f args) fs) [f]);
 
 
-  /* Remove duplicate elements from the list. O(n^2) complexity.
+  /**
+    Remove duplicate elements from the `list`. O(n^2) complexity.
+
 
-     Type: unique :: [a] -> [a]
+    # Inputs
 
-     Example:
-       unique [ 3 2 3 4 ]
-       => [ 3 2 4 ]
-   */
+    `list`
+
+    : Input list
+
+    # Type
+
+    ```
+    unique :: [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.unique` usage example
+
+    ```nix
+    unique [ 3 2 3 4 ]
+    => [ 3 2 4 ]
+    ```
+
+    :::
+  */
   unique = foldl' (acc: e: if elem e acc then acc else acc ++ [ e ]) [];
 
-  /* Check if list contains only unique elements. O(n^2) complexity.
+  /**
+    Check if list contains only unique elements. O(n^2) complexity.
+
+
+    # Inputs
+
+    `list`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    allUnique :: [a] -> bool
+    ```
 
-     Type: allUnique :: [a] -> bool
+    # Examples
+    :::{.example}
+    ## `lib.lists.allUnique` usage example
 
-     Example:
-       allUnique [ 3 2 3 4 ]
-       => false
-       allUnique [ 3 2 4 1 ]
-       => true
-   */
+    ```nix
+    allUnique [ 3 2 3 4 ]
+    => false
+    allUnique [ 3 2 4 1 ]
+    => true
+    ```
+
+    :::
+  */
   allUnique = list: (length (unique list) == length list);
 
 
-  /* Intersects list 'e' and another list. O(nm) complexity.
+  /**
+    Intersects list 'list1' and another list (`list2`).
+
+    O(nm) complexity.
 
-     Example:
-       intersectLists [ 1 2 3 ] [ 6 3 2 ]
-       => [ 3 2 ]
+    # Inputs
+
+    `list1`
+
+    : First list
+
+    `list2`
+
+    : Second list
+
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.intersectLists` usage example
+
+    ```nix
+    intersectLists [ 1 2 3 ] [ 6 3 2 ]
+    => [ 3 2 ]
+    ```
+
+    :::
   */
   intersectLists = e: filter (x: elem x e);
 
-  /* Subtracts list 'e' from another list. O(nm) complexity.
+  /**
+    Subtracts list 'e' from another list (`list2`).
+
+    O(nm) complexity.
+
+    # Inputs
+
+    `e`
+
+    : First list
+
+    `list2`
+
+    : Second list
+
+
+    # Examples
+    :::{.example}
+    ## `lib.lists.subtractLists` usage example
 
-     Example:
-       subtractLists [ 3 2 ] [ 1 2 3 4 5 3 ]
-       => [ 1 4 5 ]
+    ```nix
+    subtractLists [ 3 2 ] [ 1 2 3 4 5 3 ]
+    => [ 1 4 5 ]
+    ```
+
+    :::
   */
   subtractLists = e: filter (x: !(elem x e));
 
-  /* Test if two lists have no common element.
-     It should be slightly more efficient than (intersectLists a b == [])
+  /**
+    Test if two lists have no common element.
+    It should be slightly more efficient than (intersectLists a b == [])
+
+    # Inputs
+
+    `a`
+
+    : 1\. Function argument
+
+    `b`
+
+    : 2\. Function argument
   */
   mutuallyExclusive = a: b: length a == 0 || !(any (x: elem x a) b);
 
diff --git a/nixpkgs/lib/systems/default.nix b/nixpkgs/lib/systems/default.nix
index 6137d47e91a2..a71ea9209cb8 100644
--- a/nixpkgs/lib/systems/default.nix
+++ b/nixpkgs/lib/systems/default.nix
@@ -243,10 +243,14 @@ rec {
               vncSupport = false;
               gtkSupport = false;
               sdlSupport = false;
+              alsaSupport = false;
               pulseSupport = false;
               pipewireSupport = false;
+              jackSupport = false;
               smbdSupport = false;
               seccompSupport = false;
+              tpmSupport = false;
+              capstoneSupport = false;
               enableDocs = false;
               hostCpuTargets = [ "${final.qemuArch}-linux-user" ];
             };
diff --git a/nixpkgs/lib/tests/misc.nix b/nixpkgs/lib/tests/misc.nix
index 98d1f4e71c48..6f1d9039db80 100644
--- a/nixpkgs/lib/tests/misc.nix
+++ b/nixpkgs/lib/tests/misc.nix
@@ -13,9 +13,96 @@ Alternatively, to run all `lib` tests:
 
   [nixpkgs]$ nix-build lib/tests/release.nix
 */
-with import ../default.nix;
 
 let
+  lib = import ../default.nix;
+
+  inherit (lib)
+    allUnique
+    and
+    attrNames
+    attrsets
+    attrsToList
+    bitAnd
+    bitOr
+    bitXor
+    boolToString
+    callPackagesWith
+    callPackageWith
+    cartesianProductOfSets
+    cli
+    composeExtensions
+    composeManyExtensions
+    concatLines
+    concatMapAttrs
+    concatMapStrings
+    concatStrings
+    concatStringsSep
+    const
+    escapeXML
+    evalModules
+    filter
+    fix
+    fold
+    foldAttrs
+    foldl
+    foldl'
+    foldlAttrs
+    foldr
+    functionArgs
+    generators
+    genList
+    getExe
+    getExe'
+    groupBy
+    groupBy'
+    hasAttrByPath
+    hasInfix
+    id
+    isStorePath
+    lazyDerivation
+    lists
+    listToAttrs
+    makeExtensible
+    makeOverridable
+    mapAttrs
+    matchAttrs
+    mergeAttrs
+    meta
+    mkOption
+    mod
+    nameValuePair
+    optionalDrvAttr
+    optionAttrSetToDocList
+    overrideExisting
+    packagesFromDirectoryRecursive
+    pipe
+    range
+    recursiveUpdateUntil
+    removePrefix
+    replicate
+    runTests
+    setFunctionArgs
+    showAttrPath
+    sort
+    sortOn
+    stringLength
+    strings
+    stringToCharacters
+    systems
+    tail
+    take
+    testAllTrue
+    toBaseDigits
+    toHexString
+    toInt
+    toIntBase10
+    toShellVars
+    types
+    updateManyAttrsByPath
+    versions
+    ;
+
   testingThrow = expr: {
     expr = (builtins.tryEval (builtins.seq expr "didn't throw"));
     expected = { success = false; value = false; };
diff --git a/nixpkgs/lib/tests/modules/alias-with-priority-can-override.nix b/nixpkgs/lib/tests/modules/alias-with-priority-can-override.nix
index 9a18c9d9f613..82a4c0df8cba 100644
--- a/nixpkgs/lib/tests/modules/alias-with-priority-can-override.nix
+++ b/nixpkgs/lib/tests/modules/alias-with-priority-can-override.nix
@@ -6,12 +6,19 @@
 
 { config, lib, ... }:
 
-with lib;
+let
+  inherit (lib)
+    mkAliasOptionModule
+    mkForce
+    mkOption
+    types
+    ;
+in
 
 {
   options = {
     # A simple boolean option that can be enabled or disabled.
-    enable = lib.mkOption {
+    enable = mkOption {
       type = types.nullOr types.bool;
       default = null;
       example = true;
@@ -41,7 +48,7 @@ with lib;
     # should override the next import.
     ( { config, lib, ... }:
       {
-        enableAlias = lib.mkForce false;
+        enableAlias = mkForce false;
       }
     )
 
diff --git a/nixpkgs/lib/tests/modules/alias-with-priority.nix b/nixpkgs/lib/tests/modules/alias-with-priority.nix
index a35a06fc6974..c64a586ab2d1 100644
--- a/nixpkgs/lib/tests/modules/alias-with-priority.nix
+++ b/nixpkgs/lib/tests/modules/alias-with-priority.nix
@@ -6,12 +6,19 @@
 
 { config, lib, ... }:
 
-with lib;
+let
+  inherit (lib)
+    mkAliasOptionModule
+    mkDefault
+    mkOption
+    types
+    ;
+in
 
 {
   options = {
     # A simple boolean option that can be enabled or disabled.
-    enable = lib.mkOption {
+    enable = mkOption {
       type = types.nullOr types.bool;
       default = null;
       example = true;
@@ -41,7 +48,7 @@ with lib;
     # should be able to be overridden by the next import.
     ( { config, lib, ... }:
       {
-        enableAlias = lib.mkDefault false;
+        enableAlias = mkDefault false;
       }
     )
 
diff --git a/nixpkgs/lib/tests/modules/extendModules-168767-imports.nix b/nixpkgs/lib/tests/modules/extendModules-168767-imports.nix
index 489e6b5a5d83..6b50b81236d1 100644
--- a/nixpkgs/lib/tests/modules/extendModules-168767-imports.nix
+++ b/nixpkgs/lib/tests/modules/extendModules-168767-imports.nix
@@ -2,7 +2,14 @@
 , extendModules
 , ...
 }:
-with lib;
+
+let
+  inherit (lib)
+    mkOption
+    mkOverride
+    types
+    ;
+in
 {
   imports = [
 
diff --git a/nixpkgs/lib/trivial.nix b/nixpkgs/lib/trivial.nix
index c197822a4f8e..936ad207c03d 100644
--- a/nixpkgs/lib/trivial.nix
+++ b/nixpkgs/lib/trivial.nix
@@ -16,59 +16,114 @@ in {
 
   ## Simple (higher order) functions
 
-  /* The identity function
-     For when you need a function that does “nothing”.
+  /**
+    The identity function
+    For when you need a function that does “nothing”.
 
-     Type: id :: a -> a
+
+    # Inputs
+
+    `x`
+
+    : The value to return
+
+    # Type
+
+    ```
+    id :: a -> a
+    ```
   */
-  id =
-    # The value to return
-    x: x;
+  id = x: x;
+
+  /**
+    The constant function
+
+    Ignores the second argument. If called with only one argument,
+    constructs a function that always returns a static value.
+
+
+    # Inputs
+
+    `x`
+
+    : Value to return
+
+    `y`
+
+    : Value to ignore
+
+    # Type
+
+    ```
+    const :: a -> b -> a
+    ```
 
-  /* The constant function
+    # Examples
+    :::{.example}
+    ## `lib.trivial.const` usage example
 
-     Ignores the second argument. If called with only one argument,
-     constructs a function that always returns a static value.
+    ```nix
+    let f = const 5; in f 10
+    => 5
+    ```
 
-     Type: const :: a -> b -> a
-     Example:
-       let f = const 5; in f 10
-       => 5
+    :::
   */
   const =
-    # Value to return
     x:
-    # Value to ignore
     y: x;
 
-  /* Pipes a value through a list of functions, left to right.
+  /**
+    Pipes a value through a list of functions, left to right.
 
-     Type: pipe :: a -> [<functions>] -> <return type of last function>
-     Example:
-       pipe 2 [
-         (x: x + 2)  # 2 + 2 = 4
-         (x: x * 2)  # 4 * 2 = 8
-       ]
-       => 8
+    # Inputs
 
-       # ideal to do text transformations
-       pipe [ "a/b" "a/c" ] [
+    `value`
 
-         # create the cp command
-         (map (file: ''cp "${src}/${file}" $out\n''))
+    : Value to start piping.
 
-         # concatenate all commands into one string
-         lib.concatStrings
+    `fns`
 
-         # make that string into a nix derivation
-         (pkgs.runCommand "copy-to-out" {})
+    : List of functions to apply sequentially.
 
-       ]
-       => <drv which copies all files to $out>
+    # Type
 
-     The output type of each function has to be the input type
-     of the next function, and the last function returns the
-     final value.
+    ```
+    pipe :: a -> [<functions>] -> <return type of last function>
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.pipe` usage example
+
+    ```nix
+    pipe 2 [
+        (x: x + 2)  # 2 + 2 = 4
+        (x: x * 2)  # 4 * 2 = 8
+      ]
+    => 8
+
+    # ideal to do text transformations
+    pipe [ "a/b" "a/c" ] [
+
+      # create the cp command
+      (map (file: ''cp "${src}/${file}" $out\n''))
+
+      # concatenate all commands into one string
+      lib.concatStrings
+
+      # make that string into a nix derivation
+      (pkgs.runCommand "copy-to-out" {})
+
+    ]
+    => <drv which copies all files to $out>
+
+    The output type of each function has to be the input type
+    of the next function, and the last function returns the
+    final value.
+    ```
+
+    :::
   */
   pipe = builtins.foldl' (x: f: f x);
 
@@ -79,71 +134,197 @@ in {
 
   ## Named versions corresponding to some builtin operators.
 
-  /* Concatenate two lists
+  /**
+    Concatenate two lists
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
 
-     Type: concat :: [a] -> [a] -> [a]
+    # Type
 
-     Example:
-       concat [ 1 2 ] [ 3 4 ]
-       => [ 1 2 3 4 ]
+    ```
+    concat :: [a] -> [a] -> [a]
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.concat` usage example
+
+    ```nix
+    concat [ 1 2 ] [ 3 4 ]
+    => [ 1 2 3 4 ]
+    ```
+
+    :::
   */
   concat = x: y: x ++ y;
 
-  /* boolean “or” */
+  /**
+    boolean “or”
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
+  */
   or = x: y: x || y;
 
-  /* boolean “and” */
+  /**
+    boolean “and”
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
+  */
   and = x: y: x && y;
 
-  /* bitwise “not” */
+  /**
+    bitwise “not”
+  */
   bitNot = builtins.sub (-1);
 
-  /* Convert a boolean to a string.
+  /**
+    Convert a boolean to a string.
+
+    This function uses the strings "true" and "false" to represent
+    boolean values. Calling `toString` on a bool instead returns "1"
+    and "" (sic!).
+
+
+    # Inputs
+
+    `b`
+
+    : 1\. Function argument
 
-     This function uses the strings "true" and "false" to represent
-     boolean values. Calling `toString` on a bool instead returns "1"
-     and "" (sic!).
+    # Type
 
-     Type: boolToString :: bool -> string
+    ```
+    boolToString :: bool -> string
+    ```
   */
   boolToString = b: if b then "true" else "false";
 
-  /* Merge two attribute sets shallowly, right side trumps left
+  /**
+    Merge two attribute sets shallowly, right side trumps left
+
+    mergeAttrs :: attrs -> attrs -> attrs
+
+
+    # Inputs
+
+    `x`
+
+    : Left attribute set
+
+    `y`
+
+    : Right attribute set (higher precedence for equal keys)
 
-     mergeAttrs :: attrs -> attrs -> attrs
 
-     Example:
-       mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
-       => { a = 1; b = 3; c = 4; }
+    # Examples
+    :::{.example}
+    ## `lib.trivial.mergeAttrs` usage example
+
+    ```nix
+    mergeAttrs { a = 1; b = 2; } { b = 3; c = 4; }
+    => { a = 1; b = 3; c = 4; }
+    ```
+
+    :::
   */
   mergeAttrs =
-    # Left attribute set
     x:
-    # Right attribute set (higher precedence for equal keys)
     y: x // y;
 
-  /* Flip the order of the arguments of a binary function.
+  /**
+    Flip the order of the arguments of a binary function.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
+
+    `a`
+
+    : 2\. Function argument
 
-     Type: flip :: (a -> b -> c) -> (b -> a -> c)
+    `b`
 
-     Example:
-       flip concat [1] [2]
-       => [ 2 1 ]
+    : 3\. Function argument
+
+    # Type
+
+    ```
+    flip :: (a -> b -> c) -> (b -> a -> c)
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.flip` usage example
+
+    ```nix
+    flip concat [1] [2]
+    => [ 2 1 ]
+    ```
+
+    :::
   */
   flip = f: a: b: f b a;
 
-  /* Apply function if the supplied argument is non-null.
+  /**
+    Apply function if the supplied argument is non-null.
+
+
+    # Inputs
 
-     Example:
-       mapNullable (x: x+1) null
-       => null
-       mapNullable (x: x+1) 22
-       => 23
+    `f`
+
+    : Function to call
+
+    `a`
+
+    : Argument to check for null before passing it to `f`
+
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.mapNullable` usage example
+
+    ```nix
+    mapNullable (x: x+1) null
+    => null
+    mapNullable (x: x+1) 22
+    => 23
+    ```
+
+    :::
   */
   mapNullable =
-    # Function to call
     f:
-    # Argument to check for null before passing it to `f`
     a: if a == null then a else f a;
 
   # Pull in some builtins not included elsewhere.
@@ -155,57 +336,84 @@ in {
 
   ## nixpkgs version strings
 
-  /* Returns the current full nixpkgs version number. */
+  /**
+    Returns the current full nixpkgs version number.
+  */
   version = release + versionSuffix;
 
-  /* Returns the current nixpkgs release number as string. */
+  /**
+    Returns the current nixpkgs release number as string.
+  */
   release = lib.strings.fileContents ./.version;
 
-  /* The latest release that is supported, at the time of release branch-off,
-     if applicable.
+  /**
+    The latest release that is supported, at the time of release branch-off,
+    if applicable.
 
-     Ideally, out-of-tree modules should be able to evaluate cleanly with all
-     supported Nixpkgs versions (master, release and old release until EOL).
-     So if possible, deprecation warnings should take effect only when all
-     out-of-tree expressions/libs/modules can upgrade to the new way without
-     losing support for supported Nixpkgs versions.
+    Ideally, out-of-tree modules should be able to evaluate cleanly with all
+    supported Nixpkgs versions (master, release and old release until EOL).
+    So if possible, deprecation warnings should take effect only when all
+    out-of-tree expressions/libs/modules can upgrade to the new way without
+    losing support for supported Nixpkgs versions.
 
-     This release number allows deprecation warnings to be implemented such that
-     they take effect as soon as the oldest release reaches end of life. */
+    This release number allows deprecation warnings to be implemented such that
+    they take effect as soon as the oldest release reaches end of life.
+  */
   oldestSupportedRelease =
     # Update on master only. Do not backport.
     2311;
 
-  /* Whether a feature is supported in all supported releases (at the time of
-     release branch-off, if applicable). See `oldestSupportedRelease`. */
+  /**
+    Whether a feature is supported in all supported releases (at the time of
+    release branch-off, if applicable). See `oldestSupportedRelease`.
+
+
+    # Inputs
+
+    `release`
+
+    : Release number of feature introduction as an integer, e.g. 2111 for 21.11.
+    Set it to the upcoming release, matching the nixpkgs/.version file.
+  */
   isInOldestRelease =
-    /* Release number of feature introduction as an integer, e.g. 2111 for 21.11.
-       Set it to the upcoming release, matching the nixpkgs/.version file.
-    */
     release:
       release <= lib.trivial.oldestSupportedRelease;
 
-  /* Returns the current nixpkgs release code name.
+  /**
+    Returns the current nixpkgs release code name.
 
-     On each release the first letter is bumped and a new animal is chosen
-     starting with that new letter.
+    On each release the first letter is bumped and a new animal is chosen
+    starting with that new letter.
   */
   codeName = "Uakari";
 
-  /* Returns the current nixpkgs version suffix as string. */
+  /**
+    Returns the current nixpkgs version suffix as string.
+  */
   versionSuffix =
     let suffixFile = ../.version-suffix;
     in if pathExists suffixFile
     then lib.strings.fileContents suffixFile
     else "pre-git";
 
-  /* Attempts to return the the current revision of nixpkgs and
-     returns the supplied default value otherwise.
+  /**
+    Attempts to return the the current revision of nixpkgs and
+    returns the supplied default value otherwise.
+
+
+    # Inputs
+
+    `default`
 
-     Type: revisionWithDefault :: string -> string
+    : Default value to return if revision can not be determined
+
+    # Type
+
+    ```
+    revisionWithDefault :: string -> string
+    ```
   */
   revisionWithDefault =
-    # Default value to return if revision can not be determined
     default:
     let
       revisionFile = "${toString ./..}/.git-revision";
@@ -217,47 +425,115 @@ in {
 
   nixpkgsVersion = warn "lib.nixpkgsVersion is a deprecated alias of lib.version." version;
 
-  /* Determine whether the function is being called from inside a Nix
-     shell.
+  /**
+    Determine whether the function is being called from inside a Nix
+    shell.
 
-     Type: inNixShell :: bool
+    # Type
+
+    ```
+    inNixShell :: bool
+    ```
   */
   inNixShell = builtins.getEnv "IN_NIX_SHELL" != "";
 
-  /* Determine whether the function is being called from inside pure-eval mode
-     by seeing whether `builtins` contains `currentSystem`. If not, we must be in
-     pure-eval mode.
+  /**
+    Determine whether the function is being called from inside pure-eval mode
+    by seeing whether `builtins` contains `currentSystem`. If not, we must be in
+    pure-eval mode.
+
+    # Type
 
-     Type: inPureEvalMode :: bool
+    ```
+    inPureEvalMode :: bool
+    ```
   */
   inPureEvalMode = ! builtins ? currentSystem;
 
   ## Integer operations
 
-  /* Return minimum of two numbers. */
+  /**
+    Return minimum of two numbers.
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
+  */
   min = x: y: if x < y then x else y;
 
-  /* Return maximum of two numbers. */
+  /**
+    Return maximum of two numbers.
+
+
+    # Inputs
+
+    `x`
+
+    : 1\. Function argument
+
+    `y`
+
+    : 2\. Function argument
+  */
   max = x: y: if x > y then x else y;
 
-  /* Integer modulus
+  /**
+    Integer modulus
+
+
+    # Inputs
+
+    `base`
+
+    : 1\. Function argument
+
+    `int`
+
+    : 2\. Function argument
+
 
-     Example:
-       mod 11 10
-       => 1
-       mod 1 10
-       => 1
+    # Examples
+    :::{.example}
+    ## `lib.trivial.mod` usage example
+
+    ```nix
+    mod 11 10
+    => 1
+    mod 1 10
+    => 1
+    ```
+
+    :::
   */
   mod = base: int: base - (int * (builtins.div base int));
 
 
   ## Comparisons
 
-  /* C-style comparisons
+  /**
+    C-style comparisons
+
+    a < b,  compare a b => -1
+    a == b, compare a b => 0
+    a > b,  compare a b => 1
+
+
+    # Inputs
+
+    `a`
+
+    : 1\. Function argument
+
+    `b`
 
-     a < b,  compare a b => -1
-     a == b, compare a b => 0
-     a > b,  compare a b => 1
+    : 2\. Function argument
   */
   compare = a: b:
     if a < b
@@ -266,50 +542,100 @@ in {
          then 1
          else 0;
 
-  /* Split type into two subtypes by predicate `p`, take all elements
-     of the first subtype to be less than all the elements of the
-     second subtype, compare elements of a single subtype with `yes`
-     and `no` respectively.
+  /**
+    Split type into two subtypes by predicate `p`, take all elements
+    of the first subtype to be less than all the elements of the
+    second subtype, compare elements of a single subtype with `yes`
+    and `no` respectively.
+
+
+    # Inputs
+
+    `p`
+
+    : Predicate
+
+    `yes`
+
+    : Comparison function if predicate holds for both values
+
+    `no`
 
-     Type: (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
+    : Comparison function if predicate holds for neither value
 
-     Example:
-       let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
+    `a`
 
-       cmp "a" "z" => -1
-       cmp "fooa" "fooz" => -1
+    : First value to compare
 
-       cmp "f" "a" => 1
-       cmp "fooa" "a" => -1
-       # while
-       compare "fooa" "a" => 1
+    `b`
+
+    : Second value to compare
+
+    # Type
+
+    ```
+    (a -> bool) -> (a -> a -> int) -> (a -> a -> int) -> (a -> a -> int)
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.splitByAndCompare` usage example
+
+    ```nix
+    let cmp = splitByAndCompare (hasPrefix "foo") compare compare; in
+
+    cmp "a" "z" => -1
+    cmp "fooa" "fooz" => -1
+
+    cmp "f" "a" => 1
+    cmp "fooa" "a" => -1
+    # while
+    compare "fooa" "a" => 1
+    ```
+
+    :::
   */
   splitByAndCompare =
-    # Predicate
-    p:
-    # Comparison function if predicate holds for both values
-    yes:
-    # Comparison function if predicate holds for neither value
-    no:
-    # First value to compare
-    a:
-    # Second value to compare
-    b:
+    p: yes: no: a: b:
     if p a
     then if p b then yes a b else -1
     else if p b then 1 else no a b;
 
 
-  /* Reads a JSON file.
+  /**
+    Reads a JSON file.
 
-     Type: importJSON :: path -> any
+
+    # Inputs
+
+    `path`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    importJSON :: path -> any
+    ```
   */
   importJSON = path:
     builtins.fromJSON (builtins.readFile path);
 
-  /* Reads a TOML file.
+  /**
+    Reads a TOML file.
+
+
+    # Inputs
 
-     Type: importTOML :: path -> any
+    `path`
+
+    : 1\. Function argument
+
+    # Type
+
+    ```
+    importTOML :: path -> any
+    ```
   */
   importTOML = path:
     builtins.fromTOML (builtins.readFile path);
@@ -329,7 +655,7 @@ in {
   # TODO: figure out a clever way to integrate location information from
   # something like __unsafeGetAttrPos.
 
-  /*
+  /**
     Print a warning before returning the second argument. This function behaves
     like `builtins.trace`, but requires a string message and formats it as a
     warning, including the `warning: ` prefix.
@@ -337,28 +663,80 @@ in {
     To get a call stack trace and abort evaluation, set the environment variable
     `NIX_ABORT_ON_WARN=true` and set the Nix options `--option pure-eval false --show-trace`
 
-    Type: string -> a -> a
+    # Inputs
+
+    `msg`
+
+    : Warning message to print.
+
+    `val`
+
+    : Value to return as-is.
+
+    # Type
+
+    ```
+    string -> a -> a
+    ```
   */
   warn =
     if lib.elem (builtins.getEnv "NIX_ABORT_ON_WARN") ["1" "true" "yes"]
     then msg: builtins.trace "warning: ${msg}" (abort "NIX_ABORT_ON_WARN=true; warnings are treated as unrecoverable errors.")
     else msg: builtins.trace "warning: ${msg}";
 
-  /*
+  /**
     Like warn, but only warn when the first argument is `true`.
 
-    Type: bool -> string -> a -> a
+
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
+
+    `msg`
+
+    : 2\. Function argument
+
+    `val`
+
+    : Value to return as-is.
+
+    # Type
+
+    ```
+    bool -> string -> a -> a
+    ```
   */
   warnIf = cond: msg: if cond then warn msg else x: x;
 
-  /*
+  /**
     Like warnIf, but negated (warn if the first argument is `false`).
 
-    Type: bool -> string -> a -> a
+
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
+
+    `msg`
+
+    : 2\. Function argument
+
+    `val`
+
+    : Value to return as-is.
+
+    # Type
+
+    ```
+    bool -> string -> a -> a
+    ```
   */
   warnIfNot = cond: msg: if cond then x: x else warn msg;
 
-  /*
+  /**
     Like the `assert b; e` expression, but with a custom error message and
     without the semicolon.
 
@@ -369,33 +747,95 @@ in {
     Calls can be juxtaposed using function application, as `(r: r) a = a`, so
     `(r: r) (r: r) a = a`, and so forth.
 
-    Type: bool -> string -> a -> a
 
-    Example:
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
 
-        throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
-        lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
-        pkgs
+    `msg`
 
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    bool -> string -> a -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.throwIfNot` usage example
+
+    ```nix
+    throwIfNot (lib.isList overlays) "The overlays argument to nixpkgs must be a list."
+    lib.foldr (x: throwIfNot (lib.isFunction x) "All overlays passed to nixpkgs must be functions.") (r: r) overlays
+    pkgs
+    ```
+
+    :::
   */
   throwIfNot = cond: msg: if cond then x: x else throw msg;
 
-  /*
+  /**
     Like throwIfNot, but negated (throw if the first argument is `true`).
 
-    Type: bool -> string -> a -> a
+
+    # Inputs
+
+    `cond`
+
+    : 1\. Function argument
+
+    `msg`
+
+    : 2\. Function argument
+
+    # Type
+
+    ```
+    bool -> string -> a -> a
+    ```
   */
   throwIf = cond: msg: if cond then throw msg else x: x;
 
-  /* Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
+  /**
+    Check if the elements in a list are valid values from a enum, returning the identity function, or throwing an error message otherwise.
+
+
+    # Inputs
+
+    `msg`
 
-     Example:
-       let colorVariants = ["bright" "dark" "black"]
-       in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
-       =>
-       error: color variants: bright, black unexpected; valid ones: standard, light, dark
+    : 1\. Function argument
 
-     Type: String -> List ComparableVal -> List ComparableVal -> a -> a
+    `valid`
+
+    : 2\. Function argument
+
+    `given`
+
+    : 3\. Function argument
+
+    # Type
+
+    ```
+    String -> List ComparableVal -> List ComparableVal -> a -> a
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.checkListOfEnum` usage example
+
+    ```nix
+    let colorVariants = ["bright" "dark" "black"]
+    in checkListOfEnum "color variants" [ "standard" "light" "dark" ] colorVariants;
+    =>
+    error: color variants: bright, black unexpected; valid ones: standard, light, dark
+    ```
+
+    :::
   */
   checkListOfEnum = msg: valid: given:
     let
@@ -410,15 +850,27 @@ in {
 
   ## Function annotations
 
-  /* Add metadata about expected function arguments to a function.
-     The metadata should match the format given by
-     builtins.functionArgs, i.e. a set from expected argument to a bool
-     representing whether that argument has a default or not.
-     setFunctionArgs : (a → b) → Map String Bool → (a → b)
+  /**
+    Add metadata about expected function arguments to a function.
+    The metadata should match the format given by
+    builtins.functionArgs, i.e. a set from expected argument to a bool
+    representing whether that argument has a default or not.
+    setFunctionArgs : (a → b) → Map String Bool → (a → b)
 
-     This function is necessary because you can't dynamically create a
-     function of the { a, b ? foo, ... }: format, but some facilities
-     like callPackage expect to be able to query expected arguments.
+    This function is necessary because you can't dynamically create a
+    function of the { a, b ? foo, ... }: format, but some facilities
+    like callPackage expect to be able to query expected arguments.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
+
+    `args`
+
+    : 2\. Function argument
   */
   setFunctionArgs = f: args:
     { # TODO: Should we add call-time "type" checking like built in?
@@ -426,84 +878,133 @@ in {
       __functionArgs = args;
     };
 
-  /* Extract the expected function arguments from a function.
-     This works both with nix-native { a, b ? foo, ... }: style
-     functions and functions with args set with 'setFunctionArgs'. It
-     has the same return type and semantics as builtins.functionArgs.
-     setFunctionArgs : (a → b) → Map String Bool.
+  /**
+    Extract the expected function arguments from a function.
+    This works both with nix-native { a, b ? foo, ... }: style
+    functions and functions with args set with 'setFunctionArgs'. It
+    has the same return type and semantics as builtins.functionArgs.
+    setFunctionArgs : (a → b) → Map String Bool.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
   */
   functionArgs = f:
     if f ? __functor
     then f.__functionArgs or (functionArgs (f.__functor f))
     else builtins.functionArgs f;
 
-  /* Check whether something is a function or something
-     annotated with function args.
+  /**
+    Check whether something is a function or something
+    annotated with function args.
+
+
+    # Inputs
+
+    `f`
+
+    : 1\. Function argument
   */
   isFunction = f: builtins.isFunction f ||
     (f ? __functor && isFunction (f.__functor f));
 
-  /*
+  /**
     `mirrorFunctionArgs f g` creates a new function `g'` with the same behavior as `g` (`g' x == g x`)
     but its function arguments mirroring `f` (`lib.functionArgs g' == lib.functionArgs f`).
 
-    Type:
-      mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
-
-    Example:
-      addab = {a, b}: a + b
-      addab { a = 2; b = 4; }
-      => 6
-      lib.functionArgs addab
-      => { a = false; b = false; }
-      addab1 = attrs: addab attrs + 1
-      addab1 { a = 2; b = 4; }
-      => 7
-      lib.functionArgs addab1
-      => { }
-      addab1' = lib.mirrorFunctionArgs addab addab1
-      addab1' { a = 2; b = 4; }
-      => 7
-      lib.functionArgs addab1'
-      => { a = false; b = false; }
+
+    # Inputs
+
+    `f`
+
+    : Function to provide the argument metadata
+
+    `g`
+
+    : Function to set the argument metadata to
+
+    # Type
+
+    ```
+    mirrorFunctionArgs :: (a -> b) -> (a -> c) -> (a -> c)
+    ```
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.mirrorFunctionArgs` usage example
+
+    ```nix
+    addab = {a, b}: a + b
+    addab { a = 2; b = 4; }
+    => 6
+    lib.functionArgs addab
+    => { a = false; b = false; }
+    addab1 = attrs: addab attrs + 1
+    addab1 { a = 2; b = 4; }
+    => 7
+    lib.functionArgs addab1
+    => { }
+    addab1' = lib.mirrorFunctionArgs addab addab1
+    addab1' { a = 2; b = 4; }
+    => 7
+    lib.functionArgs addab1'
+    => { a = false; b = false; }
+    ```
+
+    :::
   */
   mirrorFunctionArgs =
-    # Function to provide the argument metadata
     f:
     let
       fArgs = functionArgs f;
     in
-    # Function to set the argument metadata to
     g:
     setFunctionArgs g fArgs;
 
-  /*
+  /**
     Turns any non-callable values into constant functions.
     Returns callable values as is.
 
-    Example:
 
-      nix-repl> lib.toFunction 1 2
-      1
+    # Inputs
+
+    `v`
+
+    : Any value
+
+
+    # Examples
+    :::{.example}
+    ## `lib.trivial.toFunction` usage example
+
+    ```nix
+    nix-repl> lib.toFunction 1 2
+    1
 
-      nix-repl> lib.toFunction (x: x + 1) 2
-      3
+    nix-repl> lib.toFunction (x: x + 1) 2
+    3
+    ```
+
+    :::
   */
   toFunction =
-    # Any value
     v:
     if isFunction v
     then v
     else k: v;
 
-  /* Convert the given positive integer to a string of its hexadecimal
-     representation. For example:
+  /**
+    Convert the given positive integer to a string of its hexadecimal
+    representation. For example:
 
-     toHexString 0 => "0"
+    toHexString 0 => "0"
 
-     toHexString 16 => "10"
+    toHexString 16 => "10"
 
-     toHexString 250 => "FA"
+    toHexString 250 => "FA"
   */
   toHexString = let
     hexDigits = {
@@ -520,14 +1021,26 @@ in {
       else hexDigits.${toString d};
   in i: lib.concatMapStrings toHexDigit (toBaseDigits 16 i);
 
-  /* `toBaseDigits base i` converts the positive integer i to a list of its
-     digits in the given base. For example:
+  /**
+    `toBaseDigits base i` converts the positive integer i to a list of its
+    digits in the given base. For example:
+
+    toBaseDigits 10 123 => [ 1 2 3 ]
+
+    toBaseDigits 2 6 => [ 1 1 0 ]
+
+    toBaseDigits 16 250 => [ 15 10 ]
+
+
+    # Inputs
+
+    `base`
 
-     toBaseDigits 10 123 => [ 1 2 3 ]
+    : 1\. Function argument
 
-     toBaseDigits 2 6 => [ 1 1 0 ]
+    `i`
 
-     toBaseDigits 16 250 => [ 15 10 ]
+    : 2\. Function argument
   */
   toBaseDigits = base: i:
     let