Search code examples
nix

nix language: why in some contexts fields can be used recursively and in others not?


I was reading nix.dev/tutorials/nix-language, and it has the following minimal package example:

{ lib, stdenv, fetchurl }:
stdenv.mkDerivation rec {
  pname = "hello";
  version = "2.12";
  src = fetchurl {
    url = "mirror://gnu/${pname}/${pname}-${version}.tar.gz";
    sha256 = "1ayhp9v4m4rdhjmnl2bq3cibrbqqkgjbl3s7yk2nhlh8vj3ay16g";
  };
  meta = with lib; {
    license = licenses.gpl3Plus;
  };
}

Notice that fetchurl {...} is using pname and version that are defined in the same structure it is defining.

Now if I try it myself I get an undefined variable (I tried in different ways):

$ nix-instantiate --eval --strict --expr 'let f = {x}: x+x ; in { a=1; b=2; c=f {x=a;}; }'
error: undefined variable 'a'
       at «string»:1:42:
            1| let f = {x}: x+x ; in { a=1; b=2; c=f {x=a;}; }
             |                                          ^

Any ideas what I'm misunderstanding here ?

Thanks!


Solution

  • Recursive set can, regular can not

    rec {
       a = 1;
       b = a;
    }.b
    

    nix eval --file a.nix

    Result:

    1
    

    vs

    {
       a = 1;
       b = a;
    }.b
    
    error: undefined variable 'a'
           at /tmp/t/b.nix:3:7:
                2|   a = 1;
                3|   b = a;
                 |       ^
                4| }.b
    

    https://nix.dev/manual/nix/2.17/language/constructs#recursive-sets