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

Set comparison throws error when attribute has error #8364

Open
Pacman99 opened this issue May 17, 2023 · 4 comments
Open

Set comparison throws error when attribute has error #8364

Pacman99 opened this issue May 17, 2023 · 4 comments
Labels
bug language The Nix expression language; parser, interpreter, primops, evaluation, etc

Comments

@Pacman99
Copy link

Pacman99 commented May 17, 2023

Describe the bug
When comparing sets where an attribute has an error, the comparison results in an error.

Steps To Reproduce
Evaluate either of the following expressions in nix repl

nix-repl> a = { a = throw "err"; }
nix-repl> a == a
error: err
nix-repl> a == { a = 5; }  
error: err

Expected behavior
In the two examples above the first one should be true and the second one should be false since the attribute sets are equal/unequal and we never tried to evaluate the attributes where the error is.

nix-env --version output
nix-env (Nix) 2.11.1

Additional context
builtins.elem has some strange behavior in this situation.

nix-repl> a = { a = throw "err"; }

nix-repl> builtins.elem a [ a ]
true

nix-repl> builtins.elem a [ { a = throw "er"; } ]
error: err

nix-repl> b = a

nix-repl> builtins.elem a [ b ]
error: err


So a workaround to compare sets could be to use builtins.elem with a list of one element, but its still problematic if the element in the list has a attribute error or if the attrset has been re-named.

Priorities

Add 👍 to issues you find important.

@Pacman99 Pacman99 added the bug label May 17, 2023
@roberth roberth added the language The Nix expression language; parser, interpreter, primops, evaluation, etc label May 19, 2023
@roberth
Copy link
Member

roberth commented May 19, 2023

Equality only works in the realm of values, not in the realm of broader evaluation outcomes. I find this to be a sensible design decision, as most of the language operates this way.
Continuing to compare after an exception raises more questions, such as "should two exceptions with different messages be considered equal value-like things?" "What if the exceptions were throw by different code or constructed in a different way, but the string value of the message is equivalent?"
There's probably even more to it than what I'm thinking of now, but another pretty strong argument is that none of the mainstream languages will catch exceptions and then carry on comparing. (At least C++, Java, Haskell, Python. Probably many languages inspired by these. Even JavaScript is consistent with these language, despite its wonky equality)

> "hello" == (function() { throw "hi" })()
Uncaught 'hi'

@sternenseemann
Copy link
Member

You just need to move the throw a bit more inwards for it to work :)

nix-repl> x = { a = { b = throw "lol"; }; }

nix-repl> x == x
true

See #3371.

@fare
Copy link

fare commented Nov 27, 2023

Having pointer equality would really help with graph algorithms that currently try to compare these attrsets by value.

@sternenseemann
Copy link
Member

sternenseemann commented Nov 28, 2023

@fare Pointer equality does exist in Nix (for better or worse), you can compare arbitrary values by pointer with a bit of trickery. Details are described e.g. here. Of course undocumented in NixOS/nix, so not necessarily certain to stay.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug language The Nix expression language; parser, interpreter, primops, evaluation, etc
Projects
None yet
Development

No branches or pull requests

4 participants