Why does this code work without rec {}?

I’m talking about this code:

If it’s not obvious, it’s basically:

{
  packages = {
    linux_5_10 = ...;
    linux_5_15 = ...;
  };

  packageAliases = {
    linux_default = if stdenv.hostPlatform.isi686 then packages.linux_5_10 else packages.linux_5_15;
  };
}

The things inside packageAliases can somehow access packages without rec {}.

Where it should’ve been:

rec {
  packages = {
    linux_5_10 = ...;
    linux_5_15 = ...;
  };

  packageAliases = {
    linux_default = if stdenv.hostPlatform.isi686 then packages.linux_5_10 else packages.linux_5_15;
  };
}

Fix point magic:

linux-kernels.nix starts with with linuxKernel;. This means that packages will be resolved to linuxKernel.packages.

all-packages.nix defines linuxKernel as linuxKernel = recurseIntoAttrs (callPackage ./linux-kernels.nix { });. This means that the linuxKernel argument in linux-kernels.nix is whatever linux-kernels.nix itself returns.

This basically simplifies to:

$ cat linux-kernels.nix
linuxKernels:
with linuxKernels;

{
  a = 1;
  b = a + 1;
}

$ cat test.nix
let lib = import <nixpkgs/lib>;
in

lib.fix (import ./linux-kernels.nix)

$ nix-instantiate --eval --strict test.nix
{ a = 1; b = 2; }
2 Likes