Skip to content

Inconsistent behaviour of attrset/list comparaison #15531

@KAction

Description

@KAction

Describe the bug

nix-repl> let u = { foo = 10; bar = (x: x); }; in u == u
true
nix-repl> let u = { foo = 10; bar = (x: x); }; in u.bar == u.bar
false
nix-repl> (x: x) == (x: x)
false
nix-repl> { foo = 10; bar = (x: x); } == { foo = 10; bar = (x: x); }
false
nix-repl> [(x: x)] == [(x: x)]
false
nix-repl> let u = [(x: x)]; in u == u
true
nix-repl> let u = [builtins.abort "foo"]; in u == u
true
-- Excuse me?! (EDIT: Nevermind, this is list of two elements, not appication).
nix-repl> [builtins.abort "foo"] == [builtins.abort "foo"]
false

Nix has inconsistent behavior when comparing lists and attrsets, more complicated than one described in
the manual.

Should we

  • consider it a bug in nixcpp (and hence c++ should be fixed). I believe that this means undoing an useful performance optimization (eq?/equal?)
  • consider it a bug in documentation, making this particular behavior an official language part, and forcing alternative implementations to do exactly the same.
  • declare comparing lists/attrsets with function values an undefined behavior
  • change both language and documentation to make functions non-comparable

From where I stand, I'd prefer option (3) and is willing to provide patches to nixpkgs, provided I get the blessing on the move direction.

Expected behavior

Not being able to break referential transparency with let bindings.

Checklist

  • checked latest Nix manual ([source])
  • checked [open bug issues and pull requests] for possible duplicates

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions