Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assert: Report why values aren't equal #11043

Merged
merged 4 commits into from
Jul 22, 2024
Merged

Conversation

roberth
Copy link
Member

@roberth roberth commented Jul 5, 2024

Motivation

assert a == b; x should report why a isn't equal to b.

With this change it does so rather well, I would say, especially when a and b are nested structures. See for example eval-fail-assert-nested-bool.err.exp.

Context

This adds code that duplicates existing behavior. I've done so to keep normal equality fast and simple.
While this approach does add a risk of the code paths diverging in the future, I believe this risk is well worth the benefit.
It makes the difference between knowing immediately why something fails, or a debugging session, changing code in a dependency, etc.

Priorities and Process

Add 👍 to pull requests you find important.

The Nix maintainer team uses a GitHub project board to schedule and track reviews.

@roberth roberth added error-messages Confusing messages and better diagnostics language The Nix expression language; parser, interpreter, primops, evaluation, etc labels Jul 5, 2024
@roberth roberth requested a review from edolstra as a code owner July 5, 2024 14:52
@github-actions github-actions bot added the with-tests Issues related to testing. PRs with tests have some priority label Jul 5, 2024
@edolstra
Copy link
Member

edolstra commented Jul 5, 2024

Looking at the AST seems pretty hacky and error-prone to me. It would be cleaner to add an assertEqual builtin.

@roberth
Copy link
Member Author

roberth commented Jul 5, 2024

Looking at the AST seems pretty hacky and error-prone to me. It would be cleaner to add an assertEqual builtin.

Evaluation is just rewriting. Rewrite rule heads matching AST constructors is nice, but not a requirement. I don't see why looking at the AST would be error prone.

I don't like assertEqual, because it expands the language unnecessarily, requiring that users learn more and remember more.

I might agree with you in cases where the language semantics is affected, but in this case it is only the error reporting. That's far from critical.

Copy link
Member

@Mic92 Mic92 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this approach more than adding a new builtin because we have a lot of existing asserts in old code. This is a nice quality of life improvement like how it currently prints the value when a type miss-matches.

// eqValues has found a difference, and it should match
// its behavior.
error<EvalBaseError>(
"cannot compare %1% with %2%; is assertEqValues out of sync with eqValues?", showType(v1), showType(v2))
Copy link
Member

@Mic92 Mic92 Jul 7, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe it should say something like BUG!. To someone not reading the c++ code ( most of the nix users) it's not clear what "eqValues" and "assertEqValues" mean.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to:

"BUG: cannot compare %1% with %2%; did forceValue leave a thunk, or might assertEqValues be out of sync with eqValues?"

}

switch (v1.type()) {
case nInt:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a way to do enforce an exhaustive c++ switch case that will fail to compile when there cases missing? Rust has this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, but we already enforce this with

  '-Werror=switch',
  '-Werror=switch-enum',

This makes the error message very hypothetical. We'd have to undo those flags, or forceValue needs to silently fail, or we'd have to read garbage, or some other chaotic thing we don't need to consider.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could a default case shadow a potential error message and should be therefore removed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The flags already prevent this despite the default, so the default is a bit paranoid.

I've changed the exceptions to crashes to aid debugging, and I've documented that they're unreachable.

roberth added 3 commits July 10, 2024 16:08
An nicer alternative to printError + abort, or assert(false /* foo */)
It's still paranoid, and probably a waste of words, but at least
now it's consistent and readily identifyable from a log.
Comment on lines +98 to +100
logError(error.info());
printError("This is a bug! An unexpected condition occurred, causing the Nix evaluator to have to stop. If you could share a reproducible example or a core dump, please open an issue at https://github.com/NixOS/nix/issues");
abort();
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A generalization of this in libutil would be nice for a follow-up.

@roberth roberth requested a review from Mic92 July 11, 2024 12:01
@edolstra edolstra merged commit d08bb02 into NixOS:master Jul 22, 2024
11 checks passed
@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/2024-07-22-nix-team-meeting-minutes-163/49544/1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
error-messages Confusing messages and better diagnostics language The Nix expression language; parser, interpreter, primops, evaluation, etc with-tests Issues related to testing. PRs with tests have some priority
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants