mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
restore proper handling of no formals vs. 0 formals
e.g. (foo@{}: 1) { a = 3; } should error, but wasn't with the previous
commit
This commit is contained in:
parent
4a80c92a4d
commit
e43888890f
9 changed files with 16 additions and 18 deletions
|
|
@ -771,7 +771,7 @@ TEST_F(PrimOpTest, derivation)
|
||||||
ASSERT_EQ(v.type(), nFunction);
|
ASSERT_EQ(v.type(), nFunction);
|
||||||
ASSERT_TRUE(v.isLambda());
|
ASSERT_TRUE(v.isLambda());
|
||||||
ASSERT_NE(v.lambda().fun, nullptr);
|
ASSERT_NE(v.lambda().fun, nullptr);
|
||||||
ASSERT_TRUE(v.lambda().fun->hasFormals());
|
ASSERT_TRUE(v.lambda().fun->hasFormals);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(PrimOpTest, currentTime)
|
TEST_F(PrimOpTest, currentTime)
|
||||||
|
|
|
||||||
|
|
@ -1496,13 +1496,13 @@ void EvalState::callFunction(Value & fun, std::span<Value *> args, Value & vRes,
|
||||||
|
|
||||||
ExprLambda & lambda(*vCur.lambda().fun);
|
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));
|
Env & env2(mem.allocEnv(size));
|
||||||
env2.up = vCur.lambda().env;
|
env2.up = vCur.lambda().env;
|
||||||
|
|
||||||
Displacement displ = 0;
|
Displacement displ = 0;
|
||||||
|
|
||||||
if (!lambda.hasFormals())
|
if (!lambda.hasFormals)
|
||||||
env2.values[displ++] = args[0];
|
env2.values[displ++] = args[0];
|
||||||
else {
|
else {
|
||||||
try {
|
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;
|
res = fun;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -490,6 +490,7 @@ struct ExprLambda : Expr
|
||||||
Symbol arg;
|
Symbol arg;
|
||||||
|
|
||||||
bool ellipsis;
|
bool ellipsis;
|
||||||
|
bool hasFormals;
|
||||||
uint16_t nFormals;
|
uint16_t nFormals;
|
||||||
Formal * formalsStart;
|
Formal * formalsStart;
|
||||||
|
|
||||||
|
|
@ -501,6 +502,7 @@ struct ExprLambda : Expr
|
||||||
: pos(pos)
|
: pos(pos)
|
||||||
, arg(arg)
|
, arg(arg)
|
||||||
, ellipsis(formals.ellipsis)
|
, ellipsis(formals.ellipsis)
|
||||||
|
, hasFormals(true)
|
||||||
, nFormals(formals.formals.size())
|
, nFormals(formals.formals.size())
|
||||||
, formalsStart(alloc.allocate_object<Formal>(nFormals))
|
, formalsStart(alloc.allocate_object<Formal>(nFormals))
|
||||||
, body(body)
|
, body(body)
|
||||||
|
|
@ -511,7 +513,7 @@ struct ExprLambda : Expr
|
||||||
ExprLambda(std::pmr::polymorphic_allocator<char> & alloc, PosIdx pos, Symbol arg, Expr * body)
|
ExprLambda(std::pmr::polymorphic_allocator<char> & alloc, PosIdx pos, Symbol arg, Expr * body)
|
||||||
: pos(pos)
|
: pos(pos)
|
||||||
, arg(arg)
|
, arg(arg)
|
||||||
, nFormals(0)
|
, hasFormals(false)
|
||||||
, formalsStart(nullptr)
|
, formalsStart(nullptr)
|
||||||
, body(body) {};
|
, body(body) {};
|
||||||
|
|
||||||
|
|
@ -529,11 +531,6 @@ struct ExprLambda : Expr
|
||||||
void setName(Symbol name) override;
|
void setName(Symbol name) override;
|
||||||
std::string showNamePos(const EvalState & state) const;
|
std::string showNamePos(const EvalState & state) const;
|
||||||
|
|
||||||
inline bool hasFormals() const
|
|
||||||
{
|
|
||||||
return nFormals > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Formal> getFormalsLexicographic(const SymbolTable & symbols) const
|
std::vector<Formal> getFormalsLexicographic(const SymbolTable & symbols) const
|
||||||
{
|
{
|
||||||
std::vector<Formal> result(getFormals().begin(), getFormals().end());
|
std::vector<Formal> result(getFormals().begin(), getFormals().end());
|
||||||
|
|
@ -551,6 +548,7 @@ struct ExprLambda : Expr
|
||||||
|
|
||||||
std::span<Formal> getFormals() const
|
std::span<Formal> getFormals() const
|
||||||
{
|
{
|
||||||
|
assert(hasFormals);
|
||||||
return {formalsStart, nFormals};
|
return {formalsStart, nFormals};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ void ExprList::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
void ExprLambda::show(const SymbolTable & symbols, std::ostream & str) const
|
void ExprLambda::show(const SymbolTable & symbols, std::ostream & str) const
|
||||||
{
|
{
|
||||||
str << "(";
|
str << "(";
|
||||||
if (hasFormals()) {
|
if (hasFormals) {
|
||||||
str << "{ ";
|
str << "{ ";
|
||||||
bool first = true;
|
bool first = true;
|
||||||
// the natural Symbol ordering is by creation time, which can lead to the
|
// 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<const StaticEnv>
|
||||||
if (es.debugRepl)
|
if (es.debugRepl)
|
||||||
es.exprEnvs.insert(std::make_pair(this, env));
|
es.exprEnvs.insert(std::make_pair(this, env));
|
||||||
|
|
||||||
auto newEnv = std::make_shared<StaticEnv>(nullptr, env, nFormals + (!arg ? 0 : 1));
|
auto newEnv = std::make_shared<StaticEnv>(nullptr, env, (hasFormals ? getFormals().size() : 0) + (!arg ? 0 : 1));
|
||||||
|
|
||||||
Displacement displ = 0;
|
Displacement displ = 0;
|
||||||
|
|
||||||
if (arg)
|
if (arg)
|
||||||
newEnv->vars.emplace_back(arg, displ++);
|
newEnv->vars.emplace_back(arg, displ++);
|
||||||
|
|
||||||
if (hasFormals()) {
|
if (hasFormals) {
|
||||||
for (auto & i : getFormals())
|
for (auto & i : getFormals())
|
||||||
newEnv->vars.emplace_back(i.name, displ++);
|
newEnv->vars.emplace_back(i.name, displ++);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3363,7 +3363,7 @@ static void prim_functionArgs(EvalState & state, const PosIdx pos, Value ** args
|
||||||
if (!args[0]->isLambda())
|
if (!args[0]->isLambda())
|
||||||
state.error<TypeError>("'functionArgs' requires a function").atPos(pos).debugThrow();
|
state.error<TypeError>("'functionArgs' requires a function").atPos(pos).debugThrow();
|
||||||
|
|
||||||
if (!args[0]->lambda().fun->hasFormals()) {
|
if (!args[0]->lambda().fun->hasFormals) {
|
||||||
v.mkAttrs(&Bindings::emptyBindings);
|
v.mkAttrs(&Bindings::emptyBindings);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -145,7 +145,7 @@ static void printValueAsXML(
|
||||||
posToXML(state, xmlAttrs, state.positions[v.lambda().fun->pos]);
|
posToXML(state, xmlAttrs, state.positions[v.lambda().fun->pos]);
|
||||||
XMLOpenElement _(doc, "function", xmlAttrs);
|
XMLOpenElement _(doc, "function", xmlAttrs);
|
||||||
|
|
||||||
if (v.lambda().fun->hasFormals()) {
|
if (v.lambda().fun->hasFormals) {
|
||||||
XMLAttrs attrs;
|
XMLAttrs attrs;
|
||||||
if (v.lambda().fun->arg)
|
if (v.lambda().fun->arg)
|
||||||
attrs["name"] = state.symbols[v.lambda().fun->arg];
|
attrs["name"] = state.symbols[v.lambda().fun->arg];
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,7 @@ static Flake readFlake(
|
||||||
if (auto outputs = vInfo.attrs()->get(sOutputs)) {
|
if (auto outputs = vInfo.attrs()->get(sOutputs)) {
|
||||||
expectType(state, nFunction, *outputs->value, outputs->pos);
|
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()) {
|
for (auto & formal : outputs->value->lambda().fun->getFormals()) {
|
||||||
if (formal.name != state.s.self)
|
if (formal.name != state.s.self)
|
||||||
flake.inputs.emplace(
|
flake.inputs.emplace(
|
||||||
|
|
|
||||||
|
|
@ -468,7 +468,7 @@ struct CmdFlakeCheck : FlakeCommand
|
||||||
if (!v.isLambda()) {
|
if (!v.isLambda()) {
|
||||||
throw Error("overlay is not a function, but %s instead", showType(v));
|
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'");
|
throw Error("overlay does not take an argument named 'final'");
|
||||||
// FIXME: if we have a 'nixpkgs' input, use it to
|
// FIXME: if we have a 'nixpkgs' input, use it to
|
||||||
// evaluate the overlay.
|
// evaluate the overlay.
|
||||||
|
|
|
||||||
|
|
@ -415,7 +415,7 @@ static void main_nix_build(int argc, char ** argv)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
bool add = 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()) {
|
for (auto & i : v.lambda().fun->getFormals()) {
|
||||||
if (state->symbols[i.name] == "inNixShell") {
|
if (state->symbols[i.name] == "inNixShell") {
|
||||||
add = true;
|
add = true;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue