Nix: `--arg/--argstr` gets ignored when variables don't occur explicitly in the argument to the top-level function

Created on 9 Aug 2015  路  8Comments  路  Source: NixOS/nix

[dfranke@pathfinder:~]$ nix-repl
Welcome to Nix version 1.9. Type :? for help.

nix-repl> #This behaves as expected

nix-repl> let f = { x ? "foo" }: x; g = y@{...}: f y; in g { x = "bar"; }
"bar"

nix-repl> :quit

[dfranke@pathfinder:~]$ cat test1.nix
let f = { x ? "foo", ... }: x; in y@{...}: f y

[dfranke@pathfinder:~]$ #This too should evaluate to "bar", not "foo"

[dfranke@pathfinder:~]$ nix-instantiate --eval --argstr x bar test1.nix
"foo"

[dfranke@pathfinder:~]$ #Now x is explicitly mentioned in the pattern

[dfranke@pathfinder:~]$ cat test2.nix
let f = { x ? "foo", ... }: x; in y@{x,...}: f y

[dfranke@pathfinder:~]$ #...and that's sufficient to produce a different result"

[dfranke@pathfinder:~]$ nix-instantiate --eval --argstr x bar test2.nix
"bar"

[dfranke@pathfinder:~]$ #Something's definitely wrong here!

Most helpful comment

3965 fixes this for real

All 8 comments

I noticed this today too. I thought I could do nix-build -A opencv --arg enableBloat true (enables GUI + Python support), but that does not work; opencv has the same output path as before. However, nix-build -A opencv --arg system \"i686-linux\" clearly works (new output path). So apparently only top-level arguments can be overridden, not anything "deeper".

Noticed this too. I tried to refactor the rtags package using a parameter for its underlying llvmPackages dependencies. Since, we have 6 different llvmPackages, it would be important to have --arg/--argstrpropagated down to the package arguments. Otherwise any package maintainer has to bloat up the top-level/all-packages.nix by multiples of its package dependencies. e.g.:

nix-env -iA rtags --argstr withllvmVersion "3.9"

is a better solution than:

rtags = callPackage ../development/tools/rtags/default.nix {
    inherit (darwin) apple_sdk;
    llvmVersion = llvmPackages;
  };

rtags_with_llvm_38 = callPackage ../development/tools/rtags/default.nix {
    inherit (darwin) apple_sdk;
    llvmVersion = llvmPackages_38;
  };

rtags_with_llvm_39 = callPackage ../development/tools/rtags/default.nix {
    inherit (darwin) apple_sdk;
    llvmVersion = llvmPackages_39;
  };

I've run into this issue as well. I've been trying to nix-env -iA nixos.pkgs.qbittorrent --arg guiSupport false (see https://github.com/NixOS/nixpkgs/blob/release-16.09/pkgs/applications/networking/p2p/qbittorrent/default.nix#L4). The problem exists since at least since 2013: http://lists.science.uu.nl/pipermail/nix-dev/2013-June/011312.html.

@edolstra @shlevy according to quick git-blame lookup you might be able to help here.

@peti A small test to reproduce this inconsistency:

test.nix

args @ { a ? "default", ... }:
builtins.trace args
(builtins.trace a
"abc")

nix-build says

$ nix-build --argstr a override test.nix
trace: { a = "override"; }
trace: override
error: expression does not evaluate to a derivation (or a set or list of those)

nix repl says

$ nix repl --argstr a override test.nix
Welcome to Nix version 2.1. Type :? for help.

Loading 'test.nix'...
trace: { }
trace: default
error: value is a string while a set was expected

The arguments seem to be never supplied to the call, if nix repl is used.

To fix this problem, go to https://github.com/NixOS/nix/blob/bba3f0a308cceb56bad4aa1efe13927360ae463f/src/nix/repl.cc#L449.

Replace this with Bindings * autoArgs = getAutoArgs(&state); and (perhaps) release it later.

This issue still occurs:

$ printf '%s\n' '{ foo ? null, ... } @ args: { inherit args; }' > a.nix
$ printf '%s\n' 'import ./a.nix' > b.nix
$ printf '%s\n' 'args: import ./a.nix args' > c.nix
$ printf '%s\n' '{ ... } @ args: import ./a.nix args' > d.nix
$ printf '%s\n' '{ foo ? false, bar ? false, ... } @ args: import ./a.nix args' > e.nix
$ printf '%s\n' '{ __functor = self: { ... } @ args: import ./a.nix args; __functionArgs = { foo = true; bar = true; }; }' > f.nix
$ nix --version
nix (Nix) 2.3.6
$ nix eval -f a.nix args
{ }
$ nix eval -f a.nix args --arg foo true
{ foo = true; }
$ nix eval -f a.nix args --arg bar true
{ }
$ nix eval -f b.nix args --arg foo true
{ foo = true; }
$ nix eval -f b.nix args --arg bar true
{ }
$ nix eval -f c.nix args
error: the expression selected by the selection path 'args' should be a set but is a function
$ nix eval -f c.nix args --arg foo true
error: the expression selected by the selection path 'args' should be a set but is a function
$ nix eval -f d.nix args --arg foo true
{ }
$ nix eval -f e.nix args
{ }
$ nix eval -f e.nix args --arg foo true
{ foo = true; }
$ nix eval -f e.nix args --arg bar true
{ bar = true; }
$ nix eval -f e.nix args --arg baz true
{ }
$ nix eval -f f.nix args
{ }
$ nix eval -f f.nix args --arg foo true
{ }
$ nix eval -f f.nix args --arg bar true
{ }
$ nix eval -f f.nix args --arg baz true
{ }

There's no way to pass through arguments without linearly returning a single function (or functor) with syntactic, non-setFunctionArgs arguments. This means you can't allow for selection from a range of functions, all recieving just the passed arguments, without duplicating every possible argument name into the wrapping function's argument set as optional arguments.

2412 only patched this issue for the REPL.

I just ran into this myself today, it was quite confusing until I found this issue. I think it should be reopened

FWIW @dingxiangfei2009's example gives a false positive of working for nix-build

test.nix

args @ { a ? "default", ... }:
builtins.trace args
(builtins.trace a
"abc")

nix-build says

$ nix-build --argstr a override test.nix
trace: { a = "override"; }
trace: override
error: expression does not evaluate to a derivation (or a set or list of those)

to correctly reproduce the issue run the following instead:

$ nix-build --argstr a override --argstr b override test.nix
trace: { a = "override"; }
trace: override
error: expression does not evaluate to a derivation (or a set or list of those)

I would have expected

trace: { a = "override"; b = "override"; }

To get this result I need to add b to the args set in test.nix.

Unfortunately, my C isn't good enough to see where the fix should go, but this issue definitely should be reopened.

3965 fixes this for real

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bryanhuntesl picture bryanhuntesl  路  3Comments

bflyblue picture bflyblue  路  3Comments

eqyiel picture eqyiel  路  3Comments

ihsanturk picture ihsanturk  路  3Comments

matthewbauer picture matthewbauer  路  3Comments