diff --git a/src/libexpr-tests/primops.cc b/src/libexpr-tests/primops.cc index 74d676844..2c2adf5d6 100644 --- a/src/libexpr-tests/primops.cc +++ b/src/libexpr-tests/primops.cc @@ -771,7 +771,7 @@ TEST_F(PrimOpTest, derivation) ASSERT_EQ(v.type(), nFunction); ASSERT_TRUE(v.isLambda()); ASSERT_NE(v.lambda().fun, nullptr); - ASSERT_TRUE(v.lambda().fun->hasFormals()); + ASSERT_TRUE(v.lambda().fun->hasFormals); } TEST_F(PrimOpTest, currentTime) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 7f16ddf8f..ec203a0d9 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1496,13 +1496,13 @@ void EvalState::callFunction(Value & fun, std::span args, Value & vRes, ExprLambda & lambda(*vCur.lambda().fun); - auto size = (!lambda.arg ? 0 : 1) + lambda.nFormals; + auto size = (!lambda.arg ? 0 : 1) + (lambda.hasFormals ? lambda.getFormals().size() : 0); Env & env2(mem.allocEnv(size)); env2.up = vCur.lambda().env; Displacement displ = 0; - if (!lambda.hasFormals()) + if (!lambda.hasFormals) env2.values[displ++] = args[0]; else { try { @@ -1747,7 +1747,7 @@ void EvalState::autoCallFunction(const Bindings & args, Value & fun, Value & res } } - if (!fun.isLambda() || !fun.lambda().fun->hasFormals()) { + if (!fun.isLambda() || !fun.lambda().fun->hasFormals) { res = fun; return; } diff --git a/src/libexpr/include/nix/expr/nixexpr.hh b/src/libexpr/include/nix/expr/nixexpr.hh index 56c378660..fbe8747c8 100644 --- a/src/libexpr/include/nix/expr/nixexpr.hh +++ b/src/libexpr/include/nix/expr/nixexpr.hh @@ -490,6 +490,7 @@ struct ExprLambda : Expr Symbol arg; bool ellipsis; + bool hasFormals; uint16_t nFormals; Formal * formalsStart; @@ -501,6 +502,7 @@ struct ExprLambda : Expr : pos(pos) , arg(arg) , ellipsis(formals.ellipsis) + , hasFormals(true) , nFormals(formals.formals.size()) , formalsStart(alloc.allocate_object(nFormals)) , body(body) @@ -511,7 +513,7 @@ struct ExprLambda : Expr ExprLambda(std::pmr::polymorphic_allocator & alloc, PosIdx pos, Symbol arg, Expr * body) : pos(pos) , arg(arg) - , nFormals(0) + , hasFormals(false) , formalsStart(nullptr) , body(body) {}; @@ -529,11 +531,6 @@ struct ExprLambda : Expr void setName(Symbol name) override; std::string showNamePos(const EvalState & state) const; - inline bool hasFormals() const - { - return nFormals > 0; - } - std::vector getFormalsLexicographic(const SymbolTable & symbols) const { std::vector result(getFormals().begin(), getFormals().end()); @@ -551,6 +548,7 @@ struct ExprLambda : Expr std::span getFormals() const { + assert(hasFormals); return {formalsStart, nFormals}; } diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc index 2fadc5e33..ce1ea19e1 100644 --- a/src/libexpr/nixexpr.cc +++ b/src/libexpr/nixexpr.cc @@ -154,7 +154,7 @@ void ExprList::show(const SymbolTable & symbols, std::ostream & str) const void ExprLambda::show(const SymbolTable & symbols, std::ostream & str) const { str << "("; - if (hasFormals()) { + if (hasFormals) { str << "{ "; bool first = true; // the natural Symbol ordering is by creation time, which can lead to the @@ -451,14 +451,14 @@ void ExprLambda::bindVars(EvalState & es, const std::shared_ptr if (es.debugRepl) es.exprEnvs.insert(std::make_pair(this, env)); - auto newEnv = std::make_shared(nullptr, env, nFormals + (!arg ? 0 : 1)); + auto newEnv = std::make_shared(nullptr, env, (hasFormals ? getFormals().size() : 0) + (!arg ? 0 : 1)); Displacement displ = 0; if (arg) newEnv->vars.emplace_back(arg, displ++); - if (hasFormals()) { + if (hasFormals) { for (auto & i : getFormals()) newEnv->vars.emplace_back(i.name, displ++); diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index 35670f451..d95c999ff 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -3363,7 +3363,7 @@ static void prim_functionArgs(EvalState & state, const PosIdx pos, Value ** args if (!args[0]->isLambda()) state.error("'functionArgs' requires a function").atPos(pos).debugThrow(); - if (!args[0]->lambda().fun->hasFormals()) { + if (!args[0]->lambda().fun->hasFormals) { v.mkAttrs(&Bindings::emptyBindings); return; } diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc index 7865e25dc..547597ca4 100644 --- a/src/libexpr/value-to-xml.cc +++ b/src/libexpr/value-to-xml.cc @@ -145,7 +145,7 @@ static void printValueAsXML( posToXML(state, xmlAttrs, state.positions[v.lambda().fun->pos]); XMLOpenElement _(doc, "function", xmlAttrs); - if (v.lambda().fun->hasFormals()) { + if (v.lambda().fun->hasFormals) { XMLAttrs attrs; if (v.lambda().fun->arg) attrs["name"] = state.symbols[v.lambda().fun->arg]; diff --git a/src/libflake/flake.cc b/src/libflake/flake.cc index dec39f738..e2fe9805e 100644 --- a/src/libflake/flake.cc +++ b/src/libflake/flake.cc @@ -281,7 +281,7 @@ static Flake readFlake( if (auto outputs = vInfo.attrs()->get(sOutputs)) { expectType(state, nFunction, *outputs->value, outputs->pos); - if (outputs->value->isLambda() && outputs->value->lambda().fun->hasFormals()) { + if (outputs->value->isLambda() && outputs->value->lambda().fun->hasFormals) { for (auto & formal : outputs->value->lambda().fun->getFormals()) { if (formal.name != state.s.self) flake.inputs.emplace( diff --git a/src/nix/flake.cc b/src/nix/flake.cc index a7e7d0039..0e499fed4 100644 --- a/src/nix/flake.cc +++ b/src/nix/flake.cc @@ -468,7 +468,7 @@ struct CmdFlakeCheck : FlakeCommand if (!v.isLambda()) { throw Error("overlay is not a function, but %s instead", showType(v)); } - if (v.lambda().fun->hasFormals() || !argHasName(v.lambda().fun->arg, "final")) + if (v.lambda().fun->hasFormals || !argHasName(v.lambda().fun->arg, "final")) throw Error("overlay does not take an argument named 'final'"); // FIXME: if we have a 'nixpkgs' input, use it to // evaluate the overlay. diff --git a/src/nix/nix-build/nix-build.cc b/src/nix/nix-build/nix-build.cc index f5c7884a9..75bae5208 100644 --- a/src/nix/nix-build/nix-build.cc +++ b/src/nix/nix-build/nix-build.cc @@ -415,7 +415,7 @@ static void main_nix_build(int argc, char ** argv) return false; } bool add = false; - if (v.type() == nFunction && v.lambda().fun->hasFormals()) { + if (v.type() == nFunction && v.lambda().fun->hasFormals) { for (auto & i : v.lambda().fun->getFormals()) { if (state->symbols[i.name] == "inNixShell") { add = true;