tvix/eval: interpolate in ./foo-${var} paths

#316
Opened by flokli at 2023-10-05T21·15+00

Following up the example from https://b.tvl.fyi/issues/281, I now got the following error:

note: while evaluating this Nix code
    --> [code]:1:1
     |
1    | (import ./derivation-attr-paths.nix) { } # uses <nixpkgs>
     | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (concatLists)
    --> /home/flokli/dev/nixos/code.tvl.fyi-submit3/tvix/derivation-attr-paths.nix:37:49
     |
37   |             ] else if recurseInto path value then lib.concatLists (
     |  _________________________________________________^
38   | |             lib.mapAttrsToList (n: go (path ++ [ n ])) value
39   | |           ) else [];
     | |___________^
note: while evaluating this Nix code
    --> /home/flokli/dev/nixos/code.tvl.fyi-submit3/tvix/derivation-attr-paths.nix:34:11
     |
34   | /           if !success then []
35   | |           else if lib.isDerivation value then [
36   | |             path
37   | |           ] else if recurseInto path value then lib.concatLists (
37   | |           ] else if recurseInto path value then lib.concatLists (
39   | |           ) else [];
     | |___________________^
note: while evaluating this as native code (force)
    --> /home/flokli/dev/nixos/code.tvl.fyi-submit3/tvix/derivation-attr-paths.nix:34:14
     |
34   |           if !success then []
     |              ^^^^^^^^
note: while evaluating this Nix code
    --> /home/flokli/dev/nixos/code.tvl.fyi-submit3/tvix/derivation-attr-paths.nix:29:20
     |
29   |           inherit (builtins.tryEval x)
     |                    ^^^^^^^^^^^^^^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/customisation.nix:86:7
     |
86   | /       if builtins.isAttrs result then
87   | |         result // {
88   | |           override = overrideArgs;
89   | |           overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
...    |
97   | |         }
98   | |       else result;
     | |_________________^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/customisation.nix:86:10
     |
86   |       if builtins.isAttrs result then
     |          ^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/applications/science/misc/colmap/default.nix:6:1
     |
6    | / assert cudaSupport -> cudaPackages != { };
7    | |
8    | | let
9    | |   boost_static = boost179.override { enableStatic = true; };
...    |
53   | |   };
54   | | }
     | |_^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/applications/science/misc/colmap/default.nix:6:8
     |
6    | assert cudaSupport -> cudaPackages != { };
     |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/applications/science/misc/colmap/default.nix:6:23
     |
6    | assert cudaSupport -> cudaPackages != { };
     |                       ^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/applications/science/misc/colmap/default.nix:6:23
     |
6    | assert cudaSupport -> cudaPackages != { };
     |                       ^^^^^^^^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:1019:5
     |
1019 |     attrs // { recurseForDerivations = true; };
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/attrsets.nix:1019:5
     |
1019 |     attrs // { recurseForDerivations = true; };
     |     ^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/customisation.nix:86:7
     |
86   | /       if builtins.isAttrs result then
87   | |         result // {
88   | |           override = overrideArgs;
89   | |           overrideDerivation = fdrv: overrideResult (x: overrideDerivation x fdrv);
...    |
97   | |         }
98   | |       else result;
     | |_________________^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/customisation.nix:86:10
     |
86   |       if builtins.isAttrs result then
     |          ^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/customisation.nix:269:16
     |
269  |       let self = f self // {
     |  ________________^
270  | |           newScope = scope: newScope (self // scope);
271  | |           callPackage = self.newScope {};
272  | |           overrideScope = g: makeScope newScope (lib.fixedPoints.extends g f);
...    |
277  | |           packages = f;
278  | |         };
     | |_________^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/customisation.nix:269:16
     |
269  |     let self = f self // {
     |                ^^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/fixed-points.nix:91:58
     |
91   |   extends = f: rattrs: self: let super = rattrs self; in super // f self super;
     |                                                          ^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/fixed-points.nix:91:67
     |
91   |   extends = f: rattrs: self: let super = rattrs self; in super // f self super;
     |                                                                   ^^^^^^^^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/fixed-points.nix:102:10
     |
102  |       in fApplied // g final prev';
     |          ^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/fixed-points.nix:102:22
     |
102  |       in fApplied // g final prev';
     |                      ^^^^^^^^^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/fixed-points.nix:102:10
     |
102  |       in fApplied // g final prev';
     |          ^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/fixed-points.nix:102:22
     |
102  |       in fApplied // g final prev';
     |                      ^^^^^^^^^^^^^
note: while evaluating this Nix code
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/fixed-points.nix:102:10
     |
102  |       in fApplied // g final prev';
     |          ^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (force)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/fixed-points.nix:102:10
     |
102  |       in fApplied // g final prev';
     |          ^^^^^^^^
note: while evaluating this as native code (listToAttrs)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/development/compilers/cudatoolkit/redist/extension.nix:132:24
     |
132  |       redistPackages = listToAttrs (concatMap wrapper (attrNames manifest));
     |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (concatMap)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/development/compilers/cudatoolkit/redist/extension.nix:132:37
     |
132  |       redistPackages = listToAttrs (concatMap wrapper (attrNames manifest));
     |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (attrNames)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/development/compilers/cudatoolkit/redist/extension.nix:132:56
     |
132  |       redistPackages = listToAttrs (concatMap wrapper (attrNames manifest));
     |                                                        ^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (foldl')
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/trivial.nix:63:8
     |
63   |     in builtins.foldl' reverseApply val functions;
     |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: while evaluating this as native code (fromJSON)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/trivial.nix:313:5
     |
313  |     builtins.fromJSON (builtins.readFile path);
     |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E029]: I/O error: /nix/var/nix/profiles/per-user/root/channels/nixos/pkgs/development/compilers/cudatoolkit/redist/manifests/redistrib_${fullCudaVersion}.json: No such file or directory (os error 2)
    --> /nix/var/nix/profiles/per-user/root/channels/nixos/lib/trivial.nix:313:24
     |
313  |     builtins.fromJSON (builtins.readFile path);
     |                        ^^^^^^^^^^^^^^^^^^^^^^

This example can be reproduced with the more minimal reproducer:

let w = "world"; in (import ./hello-${w}.nix)

Commands:

> echo "[]" > hello-world.nix
> cargo run --bin tvix -- --expr 'let w = "world"; in (import ./hello-${w}.nix)'
note: while evaluating this Nix code
 --> [code]:1:1
  |
1 | let w = "world"; in (import ./hello-${w}.nix)
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E029]: I/O error: /home/flokli/dev/nixos/code.tvl.fyi-submit3/tvix/hello-${w}.nix: No such file or directory (os error 2)
 --> [code]:1:22
  |
1 | let w = "world"; in (import ./hello-${w}.nix)
  |                      ^^^^^^^^^^^^^^^^^^^^^^^^^

warning[W003]: variable 'w' is declared, but never used:
 --> [code]:1:5
  |
1 | let w = "world"; in (import ./hello-${w}.nix)
  |     ^ variable declared here

This w should be interpolated to world, so hello-world.nix should be imported, and an empty list be returned.

  1. flokli updated the body of this issue at 2023-10-05T21·16+00
  2. Sent a PR to fix that specific occurence in https://github.com/NixOS/nixpkgs/pull/259365, but I still think we want to support this - maybe make it configurable at runtime.

    flokli at 2023-10-06T11·11+00

  3. I peeked in the rnix codebase, and looked at the generated AST via Tvixbolt

    Rnix definitely does support it properly, but it seems we're just stringify-ing these things in tvix currently.

    flokli at 2023-10-08T14·57+00

  4. The problem is that rnix parser doesn't distinguish between home paths, relative paths, absolute paths and nix paths properly on the type level, instead you need to parse the string. This is suboptimal for a number of reasons and it would probably be best if rnix would handle this.

    One concrete effect is that it is currently a catchable error when you have an empty nix path expression, i.e. <>. This should be a syntax error, i.e. fail in rnix-parser already.

    sterni at 2024-11-17T16·29+00

  5. I've already opened an issue about this: https://github.com/nix-community/rnix-parser/issues/166.

    sterni at 2024-11-17T16·29+00