Print the value in value is X while a Y is expected error#9753
Print the value in value is X while a Y is expected error#9753roberth merged 1 commit intoNixOS:masterfrom
value is X while a Y is expected error#9753Conversation
value is X while a Y is expected error
04bb0d0 to
004bfaf
Compare
Ma27
left a comment
There was a problem hiding this comment.
This is a very nice change!
I played a bit around with this and it seems to be working fine. I even through this against some more complex evaluations involving flake-parts with custom modules and that seems to be producing helpful results.
From what I can tell, this looks OK code-wise from what I can tell - haven't been doing contributing much to the Nix codebase recently.
One issue I noticed however is that the opening bracket of a list/attr-set is magenta, the closing bracket isn't, i.e.
"[...] while a set was expected: " ANSI_MAGENTA "[" ANSI_CYAN " 2 3 " ANSI_NORMAL "]"
E.g. reproducible with ./result/bin/nix-instantiate --eval -E '[ 1 2 ] // {}'.
Also, I'm wondering if it'd make sense to do a little bit of pretty-printing for lists and attr-sets, though that'd require changes on existing code, so that's a follow-up I guess.
664d1b1 to
1c1225a
Compare
src/libexpr/eval.cc
Outdated
| #include <iostream> | ||
| #include <fstream> | ||
| #include <functional> | ||
| #include <strstream> |
There was a problem hiding this comment.
Btw any particular reason for using strstream here? That is deprecated for quite a while and I just realized that it doesn't build with clang (used gcc last time).
Also, reversing this change seems fine as well.
There was a problem hiding this comment.
Nope, fixed this to use iostream instead.
Needed to fix the build with clang. See also NixOS#9753 (comment)
Low-hanging fruit in the spirit of NixOS#9753 and NixOS#9754 (means 9999years did all the hard work already). This basically prints out what was attempted to be called as function, i.e. map (import <nixpkgs> {}) [ 1 2 3 ] now gives the following error message: error: … while calling the 'map' builtin at «string»:1:1: 1| map (import <nixpkgs> {}) [ 1 2 3 ] | ^ … while evaluating the first argument passed to builtins.map error: expected a function but found a set: { _type = "pkgs"; AAAAAASomeThingsFailToEvaluate = «thunk»; AMB-plugins = «thunk»; ArchiSteamFarm = «thunk»; BeatSaberModManager = «thunk»; CHOWTapeModel = «thunk»; ChowCentaur = «thunk»; ChowKick = «thunk»; ChowPhaser = «thunk»; CoinMP = «thunk»; «18783 attributes elided»}
1c1225a to
56be92f
Compare
Adds the failing value to `value is <TYPE> while a <TYPE> is expected` error messages.
56be92f to
cb7fbd4
Compare
This is caused by the formatting logic behind As for the magenta token, you could wrap all expressions in |
|
That's a good idea. Can I leave it to a follow-up PR to keep this focused? |
👍 |
Low-hanging fruit in the spirit of NixOS#9753 and NixOS#9754 (means 9999years did all the hard work already). This basically prints out what was attempted to be called as function, i.e. map (import <nixpkgs> {}) [ 1 2 3 ] now gives the following error message: error: … while calling the 'map' builtin at «string»:1:1: 1| map (import <nixpkgs> {}) [ 1 2 3 ] | ^ … while evaluating the first argument passed to builtins.map error: expected a function but found a set: { _type = "pkgs"; AAAAAASomeThingsFailToEvaluate = «thunk»; AMB-plugins = «thunk»; ArchiSteamFarm = «thunk»; BeatSaberModManager = «thunk»; CHOWTapeModel = «thunk»; ChowCentaur = «thunk»; ChowKick = «thunk»; ChowPhaser = «thunk»; CoinMP = «thunk»; «18783 attributes elided»}
While preparing PRs like NixOS#9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: EvalErrorBuilder<TypeError>(state, "'%s' is not a string", getAttrPathStr()) .debugThrow()
While preparing PRs like NixOS#9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: EvalErrorBuilder<TypeError>(state, "'%s' is not a string", getAttrPathStr()) .debugThrow()
While preparing PRs like NixOS#9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: EvalErrorBuilder<TypeError>(state, "'%s' is not a string", getAttrPathStr()) .debugThrow()
While preparing PRs like NixOS#9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: EvalErrorBuilder<TypeError>(state, "'%s' is not a string", getAttrPathStr()) .debugThrow()
While preparing PRs like NixOS#9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: state.error<TypeError>("'%s' is not a string", getAttrPathStr()) .debugThrow() The type annotation has moved from `ErrorBuilder::debugThrow` to `EvalState::error`.
While preparing PRs like NixOS#9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: state.error<TypeError>("'%s' is not a string", getAttrPathStr()) .debugThrow() The type annotation has moved from `ErrorBuilder::debugThrow` to `EvalState::error`.
While preparing PRs like NixOS#9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: state.error<TypeError>("'%s' is not a string", getAttrPathStr()) .debugThrow() The type annotation has moved from `ErrorBuilder::debugThrow` to `EvalState::error`.
This fixes the opening bracket of lists/attrsets being printed in magenta, unlike the closing bracket. NixOS#9753 (comment)
This fixes the opening bracket of lists/attrsets being printed in magenta, unlike the closing bracket. NixOS#9753 (comment)
Print the value in `value is X while a Y is expected` error (cherry picked from commit 5f72a97) Change-Id: Idb4bc903ae59a0f5b6fb3b1da4d47970fe0a6efe
While preparing PRs like NixOS#9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: state.error<TypeError>("'%s' is not a string", getAttrPathStr()) .debugThrow() The type annotation has moved from `ErrorBuilder::debugThrow` to `EvalState::error`. (cherry picked from commit c6a89c1) Change-Id: Iced91ba4e00ca9e801518071fb43798936cbd05a
Motivation
Adds the failing value to
value is <TYPE> while a <TYPE> is expectederror messages.Context
Take two of #9554 now that #9606 is merged.
Partial fix for #561, in particular #561 (comment).
Priorities
Add 👍 to pull requests you find important.