about summary refs log tree commit diff
diff options
context:
space:
mode:
authorGriffin Smith <grfn@gws.fyi>2020-08-27T15·58-0400
committerglittershark <grfn@gws.fyi>2020-08-28T01·18+0000
commitfb0528c5dada2d3af6152b37a46e505e6bb2ac94 (patch)
treefa921ed14ef82642d1454ef5adff1f56fdf00037
parent3bada1d41eed3bd8c72d6811147cd100fcb585ca (diff)
fix(tvix): Pass all args when auto-calling a function with an ellipsis r/1727
The command line options --arg and --argstr that are used by a bunch of
CLI commands to pass arguments to top-level functions in files go
through the same code-path as auto-calling top-level functions with
their default arguments - this, however, was only passing the arguments
that were *explicitly* mentioned in the formals of the function - in the
case of an as-pattern with an ellipsis (eg args @ { ... }) extra passed
arguments would get omitted. This fixes that to instead pass *all*
specified auto args in the case that our function has an ellipsis.

Submitted upstream at https://github.com/NixOS/nix/pull/3965

Fixes: #46
Change-Id: I32b7ee0e5bacf75b2bc43a3f0796f533f4bd5959
Reviewed-on: https://cl.tvl.fyi/c/depot/+/1863
Reviewed-by: tazjin <mail@tazj.in>
Tested-by: BuildkiteCI
-rw-r--r--third_party/nix/src/libexpr/eval.cc29
-rw-r--r--third_party/nix/src/nix-build/nix-build.cc1
2 files changed, 21 insertions, 9 deletions
diff --git a/third_party/nix/src/libexpr/eval.cc b/third_party/nix/src/libexpr/eval.cc
index 569e04e3a712..b735495f2132 100644
--- a/third_party/nix/src/libexpr/eval.cc
+++ b/third_party/nix/src/libexpr/eval.cc
@@ -1117,15 +1117,26 @@ void EvalState::autoCallFunction(Bindings* args, Value& fun, Value& res) {
   Value* actualArgs = allocValue();
   mkAttrs(*actualArgs, fun.lambda.fun->formals->formals.size());
 
-  for (auto& i : fun.lambda.fun->formals->formals) {
-    Bindings::iterator j = args->find(i.name);
-    if (j != args->end()) {
-      actualArgs->attrs->push_back(j->second);
-    } else if (i.def == nullptr) {
-      throwTypeError(
-          "cannot auto-call a function that has an argument without a default "
-          "value ('%1%')",
-          i.name);
+  if (fun.lambda.fun->formals->ellipsis) {
+    // If the formals have an ellipsis (eg the function accepts extra args) pass
+    // all available automatic arguments (which includes arguments specified on
+    // the command line via --arg/--argstr)
+    for (auto& [_, v] : *args) {
+      actualArgs->attrs->push_back(v);
+    }
+  } else {
+    // Otherwise, only pass the arguments that the function accepts
+    for (auto& i : fun.lambda.fun->formals->formals) {
+      Bindings::iterator j = args->find(i.name);
+      if (j != args->end()) {
+        actualArgs->attrs->push_back(j->second);
+      } else if (i.def == nullptr) {
+        throwTypeError(
+            "cannot auto-call a function that has an argument without a "
+            "default "
+            "value ('%1%')",
+            i.name);
+      }
     }
   }
 
diff --git a/third_party/nix/src/nix-build/nix-build.cc b/third_party/nix/src/nix-build/nix-build.cc
index 67cd8252f07e..30ab2a8136d2 100644
--- a/third_party/nix/src/nix-build/nix-build.cc
+++ b/third_party/nix/src/nix-build/nix-build.cc
@@ -270,6 +270,7 @@ static void _main(int argc, char** argv) {
 
   if (packages) {
     std::ostringstream joined;
+    // TODO(grfn): Generate a syntax tree here, not a string
     joined << "with import <nixpkgs> { }; (pkgs.runCommandCC or "
               "pkgs.runCommand) \"shell\" { buildInputs = [ ";
     for (const auto& i : left) {