Skip to content

lib/modules: add 'index' to module.args of listOf submodule#445774

Draft
hsjobeki wants to merge 1 commit intoNixOS:masterfrom
hsjobeki:lib-modules-list-index
Draft

lib/modules: add 'index' to module.args of listOf submodule#445774
hsjobeki wants to merge 1 commit intoNixOS:masterfrom
hsjobeki:lib-modules-list-index

Conversation

@hsjobeki
Copy link
Contributor

@hsjobeki hsjobeki commented Sep 24, 2025

Allow to access index through module args, equivalent to attrsOf submodule

Example:

       options.lili = mkOption {
          type = types.listOf (types.submoduleWith {
            modules = [
              (
                { index, ...}: {
                  options.idx = lib.mkOption { default = index; };
                }
              )
            ];
          });
        };

Tested so far:

  • Allows submodules to depend on the final index in a list.
  • Allows lazy access to other elements in the list.

TODO:

  • Find a better way of doing list concatenation in listOf merge
  • Get the idea approved
  • handle filter (x: x.optionalValue ? value)

Combination with operators:

The following is working because the existence of a submodule cannot be filtered by using mkIf
otherwise this would introduce paradoxons such as:

[ (mkIf (index == 0) { }) { } ]
=>
[ { } { } ]

The first submodule would simply not receive any definitions but cannot be removed from the list. (current behavior)

Things done

  • Built on platform:
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • Tested, as applicable:
  • Ran nixpkgs-review on this PR. See nixpkgs-review usage.
  • Tested basic functionality of all binary files, usually in ./result/bin/.
  • Nixpkgs Release Notes
    • Package update: when the change is major or breaking.
  • NixOS Release Notes
    • Module addition: when adding a new NixOS module.
    • Module update: when the change is significant.
  • Fits CONTRIBUTING.md, pkgs/README.md, maintainers/README.md and other READMEs.

Add a 👍 reaction to pull requests you find important.

@hsjobeki hsjobeki force-pushed the lib-modules-list-index branch from 997b6de to df9aeab Compare September 24, 2025 12:19
@nixpkgs-ci nixpkgs-ci bot added 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux. 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 6.topic: module system About "NixOS" module system internals 6.topic: lib The Nixpkgs function library labels Sep 24, 2025
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/how-to-default-an-option-based-on-its-index-in-a-listof/31769/5

@roberth
Copy link
Member

roberth commented Oct 13, 2025

I always thought name was a mistake, and it would have been better to handle this in the type declaration: attrsWith { elem = name: submodule { config._module.args.name = name; }; }, so I'm not so sure that we should repeat the same pattern here. The implementation looks painful and it seems this will have a runtime cost that applies to all lists.
Not to mention that lists don't support other things like import order invariance or element overriding.

@hsjobeki
Copy link
Contributor Author

Yes i also fear this has performance problems; obviously due to the list concatenation.
I couldn't find a better way yet to keep an incrementing counter. I discussed this feature with @Lassulus for usage in disko, but currently a local workaround needs to be maintained.

# If this worked, filtering would introduces paradoxons, for example:
# [ (mkIf (index == 0) { }) { } ]
value = map (x: x.optionalValue.value or x.mergedValue) (
filter (x: x.optionalValue ? value) evals.res
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIUC assuming m is sensitive to the index, a definition like [ m (lib.mkIf false n) m ] would produce indexes 0 and 2 instead of 0 and 1, because of this logic here.
Ideally that could just be fixed, but it might be ok to just fail, i.e. return [ r1 r2 r3 ] where r2 throws an error. That way at least the numbering is predictable in all cases where it produces a valid config.

{
file = "<internal>";
value = {
_module.args.index = acc.total + m - 1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

with imap0

Suggested change
_module.args.index = acc.total + m - 1;
_module.args.index = acc.total + m;

@roberth
Copy link
Member

roberth commented Oct 14, 2025

the list concatenation.

  • lib.linkedLists: init #452088 has an O(n log n) concatenation that you could do afterwards. Just return a linked list from the foldl'. Probably bad constant factor because of the extra allocations fwiw.

@nixpkgs-ci nixpkgs-ci bot added the 2.status: merge conflict This PR has merge conflicts with the target branch label Jan 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

2.status: merge conflict This PR has merge conflicts with the target branch 6.topic: lib The Nixpkgs function library 6.topic: module system About "NixOS" module system internals 10.rebuild-darwin: 1-10 This PR causes between 1 and 10 packages to rebuild on Darwin. 10.rebuild-darwin: 1 This PR causes 1 package to rebuild on Darwin. 10.rebuild-linux: 1-10 This PR causes between 1 and 10 packages to rebuild on Linux.

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

3 participants