Skip to content

Commit

Permalink
libnixf: fix variable lookup not visiting empty let ... in ... expr
Browse files Browse the repository at this point in the history
Emtpy let ... in ... expression, leaving a nullptr in libnixf's "Let" struct,
causes the code not continue visiting the body at all.

Fixes: #500
  • Loading branch information
inclyc committed May 18, 2024
1 parent 0694e8d commit c1d9c34
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 8 deletions.
27 changes: 19 additions & 8 deletions libnixf/src/Sema/VariableLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,15 +220,26 @@ void VariableLookupAnalysis::dfs(const ExprAttrs &Attrs,

void VariableLookupAnalysis::dfs(const ExprLet &Let,
const std::shared_ptr<EnvNode> &Env) {
if (!Let.attrs())
return;
const SemaAttrs &SA = Let.attrs()->sema();
assert(SA.isRecursive() && "let ... in ... attrset must be recursive");
std::shared_ptr<EnvNode> NewEnv = dfsAttrs(SA, Env, &Let, Definition::DS_Let);
if (Let.expr())
dfs(*Let.expr(), NewEnv);

emitEnvLivenessWarning(NewEnv);
// Obtain the env object suitable for "in" expression.
auto GetLetEnv = [&Env, &Let, this]() -> std::shared_ptr<EnvNode> {
// This is an empty let ... in ... expr, definitely anti-pattern in
// nix language. We want to passthrough the env then.
if (!Let.attrs()) {
return Env;
}

// If there are some attributes actually, create a new env.
const SemaAttrs &SA = Let.attrs()->sema();
assert(SA.isRecursive() && "let ... in ... attrset must be recursive");
return dfsAttrs(SA, Env, &Let, Definition::DS_Let);
};

auto LetEnv = GetLetEnv();

if (Let.expr())
dfs(*Let.expr(), LetEnv);
emitEnvLivenessWarning(LetEnv);
}

void VariableLookupAnalysis::trivialDispatch(
Expand Down
10 changes: 10 additions & 0 deletions libnixf/test/Sema/VariableLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,4 +280,14 @@ TEST_F(VLATest, InheritRec) {
ASSERT_EQ(Diags.size(), 0);
}

TEST_F(VLATest, EmptyLetIn) {
// Test that emtpy let ... in ... expression is considered.
// https://github.com/nix-community/nixd/issues/500
std::shared_ptr<Node> AST = parse("{ config }: let in config", Diags);
VariableLookupAnalysis VLA(Diags);
VLA.runOnAST(*AST);

ASSERT_EQ(Diags.size(), 0);
}

} // namespace

0 comments on commit c1d9c34

Please sign in to comment.