aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/eval.cc
diff options
context:
space:
mode:
authorregnat <rg@regnat.ovh>2022-03-08 16:20:01 +0100
committerregnat <rg@regnat.ovh>2022-03-08 16:40:22 +0100
commitf6078e474d5fc41c8a7f683865d60490bf0c7040 (patch)
treec927f410db27a5589db269959508b14302188d11 /src/libexpr/eval.cc
parent33b7514035a967df2ab61ab9770627157aa4f5c5 (diff)
Also display some suggestions for invalid formal arguments
```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.
Diffstat (limited to 'src/libexpr/eval.cc')
-rw-r--r--src/libexpr/eval.cc23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 3bfb82b16..a5e9dc286 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -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));
@@ -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
}
}