about summary refs log tree commit diff
path: root/tvix/eval
diff options
context:
space:
mode:
authorsterni <sternenseemann@systemli.org>2023-06-26T23·20+0200
committerclbot <clbot@tvl.fyi>2023-07-11T16·17+0000
commit8adc9c56f21d8418dc5f4b73a4327d04cd10ebd3 (patch)
tree2ca1804e337763b359e79d26878cb9238bdfa54c /tvix/eval
parent4ba624efae2d63057c2bd5be23841be5017bd457 (diff)
docs(tvix): document when pointer equality is preserved in C++ Nix r/6405
This explicitly documents behavior of C++ Nix that goes against the
intuition you'd gather from this document: that e.g. a simple select
from an attribute set causes a value to no longer be pointer equal to
its former self.

The point of documenting this is that we can show in a to be written
section on the use of pointer equality in nixpkgs that pointer equality
is only needed in a limited sense for evaluating it (C++ Nix's exterior
pointer equality). Tvix's pointer equality is far more powerful since
value identity preserving operations also preserve pointer equality,
generally speaking (this is because we implement interior pointer
equality in my made up terminology). This should eventually also be
documented.

Change-Id: I6ce7ef2d67b012f5ebc92f9e81bba33fb9dce7d0
Reviewed-on: https://cl.tvl.fyi/c/depot/+/8856
Tested-by: BuildkiteCI
Autosubmit: sterni <sternenseemann@systemli.org>
Reviewed-by: tazjin <tazjin@tvl.su>
Diffstat (limited to 'tvix/eval')
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp2
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix13
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.exp1
-rw-r--r--tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.nix28
4 files changed, 39 insertions, 5 deletions
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp
index eb05f4caf0..097eb2033a 100644
--- a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.exp
@@ -1 +1 @@
-[ true true true true true true true true false false true ]
+[ true true true true true true true true true true ]
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix
index 678d6139ee..aa2a0a1e19 100644
--- a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-builtins-set-pointer-equality.nix
@@ -12,9 +12,14 @@ in
   (alias == builtins.builtins)
   ([ builtins ] == [ builtins ])
 
-  # Surprisingly this only works with the set
-  ([ builtins.add ] == [ builtins.add ])
-  ({ inherit (builtins) import; } == { inherit (builtins) import; })
-  # But this does
+  # Surprisingly the following expressions don't work. They are
+  # here for documentation purposes and covered only
+  # by eval-okay-select-pointer-inequality.nix. Reasoning is that
+  # we may not want / be able to replicate this behavior at all.
+  #   ([ builtins.add ] == [ builtins.add ])
+  #   ({ inherit (builtins) import; } == { inherit (builtins) import; })
+
+  # These expressions work as expected, however:
   (let x = { inherit (builtins) add; }; in x == x)
+  (let inherit (builtins) add; in [ add ] == [ add ])
 ]
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.exp b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.exp
new file mode 100644
index 0000000000..69fd1d0847
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.exp
@@ -0,0 +1 @@
+[ false false false false false true false false ]
diff --git a/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.nix b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.nix
new file mode 100644
index 0000000000..821aa47a0d
--- /dev/null
+++ b/tvix/eval/src/tests/tvix_tests/notyetpassing/eval-okay-non-identifier-pointer-inequality.nix
@@ -0,0 +1,28 @@
+# C++ Nix frequently creates copies of Value structs when evaluating
+# a variety of expressions. As a result, pointer equality doesn't
+# work for many (all?) expressions that go beyond simple identifier
+# access from the scope: Even if the inner representation of the
+# value still has the same memory location, C++ Nix has created
+# a copy of the struct that holds the pointer to this memory.
+# Since pointer equality is established via the location of
+# the latter, not the former, the values are no longer equal
+# by pointer.
+let
+  foo = { bar = x: x; };
+
+  id = x: x;
+in
+
+[
+  ({ inherit (foo) bar; } == { inherit (foo) bar; })
+  ([ foo.bar ] == [ foo.bar ])
+
+  ([ builtins.add ] == [ builtins.add ])
+  ({ inherit (builtins) import; } == { inherit (builtins) import; })
+
+  ([ (id id) ] == [ (id id) ])
+  ([ id ] == [ id ])
+
+  (with foo; [ bar ] == [ bar ])
+  (with builtins; [ add ] == [ add ])
+]