When I try to build as part of a nix-darwin configuration, I get an infinite recursion encountered error:
building the system configuration...
error: while evaluating 'evalModules' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:62:17, called from /nix/store/0882sb0p0lhf4b964apsbbfpijl94ngz-darwin/darwin/eval-config.nix:25:10:
while evaluating the attribute '_module.freeformType' at undefined position:
while evaluating 'g' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/attrsets.nix:276:19, called from undefined position:
while evaluating anonymous function at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:139:72, called from /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/attrsets.nix:279:20:
while evaluating the attribute 'value' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:512:9:
while evaluating the option `_module.freeformType':
while evaluating the attribute 'mergedValue' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:544:5:
while evaluating the attribute 'values' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:538:9:
while evaluating the attribute 'values' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:637:7:
while evaluating 'byName' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:362:25, called from /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:378:22:
while evaluating 'byName' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:362:25, called from /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:374:21:
while evaluating anonymous function at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:337:19, called from /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:337:8:
while evaluating 'pushDownProperties' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:576:24, called from /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:337:73:
while evaluating 'pushDownProperties' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:576:24, called from /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:578:7:
while evaluating the module argument `config' in "/Users/eturkeltaub/tilde/modules/configuration":
while evaluating the attribute 'config' at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:130:21:
infinite recursion encountered, at /nix/store/pci4ssg62nr8mg3kax4ccrpzbz4vn5lc-nixpkgs-21.03pre262944.f18ba0425d8/nixpkgs/lib/modules.nix:130:21
It seems like I can’t refer to cfg inside of mkMerge, but I have no idea why that’s the case. Can anyone help me out?
In theory the result of mkmerge could contain new options for tilde.modules.configuration therefore it’s recursing infinitely. You need to make sure that this overlap can not happen.
As it potentially can have those keys, it would mean that those options would need to be merged again due to how the nodule system and final merging works.
Merge them under a key that is not tilde and it should work without infinite recursion.
No, I meant something like config.foo = mkMerhe ...
As long as you merge directly into the top-level config, you will keep the the infinite recursion as your merged results still could contain the keys you want to merge over.
Is there any way to apply this sort of pattern then, where some configurations get merged into the top level? I could use an example, I’m a bit of a Nix newcomer
Basically I’d like to have definitions for machines (nix-darwin or NixOS) and definitions for users (home-manager) and then use combinations of those to create a configuration. I could do this with just imports but I like the module pattern because it allows for a set of required options and merges applies that to a default configuration (so I can pass the networking hostname to a machine definition, and it will merge that in with the rest of the default machine configuration).
Common approach is to provide different entrypoint for the config using nixos-config entry in the nix path. Or even provide host and user entries to import from.
The actual module I was trying to make was larger, but I broke it down to this.
What I don’t really understand, why would it cause an infinite recursion error, if it could contain options for itself? Shouldn’t the infinite recursion be caused by the containing itself instead of the possibility?
no. the infinite recursion is caused by some config attribute depending, in some way, on itself in a way the module system cannot resolve. config (the argument) is (to first approximation) a fixed point of mkMerge, so try to imagine the config (attribute) you write as though every config (argument) had been replaced with the entire value bound to config (attribute). in your first case this process goes on forever, so you get an infinite recursion. in your second example it stops after one iteration, so you don’t get an infinite recursion.
importantly note that nix is a lazy language, so only values that are actually used count towards producing an infinite recursion. that’s why you get an infinite recursion out of
the first case uses the attribute names (and thus the value) of config, the second one does not use config at all. if we introduce a use of config with a trace we get an infinite recursion again:
Just last week I held a Nix Hour relating to recursion in the module system, and it also covered getting infinite recursion with mkMerge and how to work around it. Feel free to check it out, comes with timestamps https://www.youtube.com/live/cZjOzOHb2ow