Skip to content

Commit

Permalink
Also display some suggestions for invalid formal arguments
Browse files Browse the repository at this point in the history
```console
$ nix eval --expr '({ foo ? 1 }: foo) { fob = 2; }'
error: anonymous function at (string):1:2 called with unexpected argument 'fob'

       at «string»:1:1:

            1| ({ foo ? 1 }: foo) { fob = 2; }
             | ^
       Did you mean foo?
```

Not that because Nix will first check for _missing_ arguments before
checking for extra arguments, `({ foo }: foo) { fob = 1; }` will
complain about the missing `foo` argument (rather than extra `fob`) and
so won’t display a suggestion.
  • Loading branch information
thufschmitt committed Mar 8, 2022
1 parent 33b7514 commit f6078e4
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 2 deletions.
23 changes: 21 additions & 2 deletions src/libexpr/eval.cc
Original file line number Diff line number Diff line change
Expand Up @@ -782,6 +782,16 @@ LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const char * s, const
});
}

LocalNoInlineNoReturn(void throwTypeError(const Pos & pos, const Suggestions & suggestions, const char * s, const ExprLambda & fun, const Symbol & s2))
{
throw TypeError(ErrorInfo {
.msg = hintfmt(s, fun.showNamePos(), s2),
.errPos = pos,
.suggestions = suggestions,
});
}


LocalNoInlineNoReturn(void throwTypeError(const char * s, const Value & v))
{
throw TypeError(s, showType(v));
Expand Down Expand Up @@ -1414,8 +1424,17 @@ void EvalState::callFunction(Value & fun, size_t nrArgs, Value * * args, Value &
/* Nope, so show the first unexpected argument to the
user. */
for (auto & i : *args[0]->attrs)
if (!lambda.formals->has(i.name))
throwTypeError(pos, "%1% called with unexpected argument '%2%'", lambda, i.name);
if (!lambda.formals->has(i.name)) {
std::set<std::string> formalNames;
for (auto & formal : lambda.formals->formals)
formalNames.insert(formal.name);
throwTypeError(
pos,
Suggestions::bestMatches(formalNames, i.name),
"%1% called with unexpected argument '%2%'",
lambda,
i.name);
}
abort(); // can't happen
}
}
Expand Down
4 changes: 4 additions & 0 deletions tests/suggestions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,7 @@ NIX_BUILD_STDERR_WITH_NO_CLOSE_SUGGESTION=$(! nix build .\#bar 2>&1 1>/dev/null)
NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '(builtins.getFlake (builtins.toPath ./.)).packages.'$system'.fob' 2>&1 1>/dev/null)
[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean one of fo1, fo2, foo or fooo?" ]] || \
fail "The evaluator should suggest the three closest possiblities"

NIX_EVAL_STDERR_WITH_SUGGESTIONS=$(! nix build --impure --expr '({ foo }: foo) { foo = 1; fob = 2; }' 2>&1 1>/dev/null)
[[ "$NIX_EVAL_STDERR_WITH_SUGGESTIONS" =~ "Did you mean foo?" ]] || \
fail "The evaluator should suggest the three closest possiblities"

0 comments on commit f6078e4

Please sign in to comment.