| 9 Nov 2025 |
raitobezarius | thx | 16:46:17 |
raitobezarius | a fix may rain in the next hours | 16:47:18 |
raitobezarius | i want to go and say that zomg the fact that we broke eval based on this behavior :') | 16:51:32 |
Lunaphied | Dear gods that's horrifying | 16:58:33 |
Winter | i fucking hate it | 16:58:49 |
Sergei Zimmerman (xokdvium) | What's even more cursed is this:
nix::EvalState::eqValues (this=0x555555e8b770, v1=..., v2=..., pos=..., errorCtx="while testing two values for equality") at lix/libexpr/eval.cc:2613
2613 forceValue(v2, pos);
(gdb)
2616 if (v1.type() == nInt && v2.type() == nFloat) {
(gdb)
2619 if (v1.type() == nFloat && v2.type() == nInt) {
(gdb)
2624 if (v1.type() != v2.type()) return false;
(gdb)
2629 auto pointerEq = [&] { return v1.pointerEqProxy() == v2.pointerEqProxy(); };
(gdb)
2631 switch (v1.type()) {
(gdb)
2658 if (pointerEq()) return true;
(gdb)
2661 if (isDerivation(v1) && isDerivation(v2)) {
(gdb)
2669 if (v1.attrs()->size() != v2.attrs()->size()) return false;
(gdb) p v1.attrs()->size()
$1 = 2
(gdb) p v2.attrs()->size()
$2 = 3
It's not equal because the attrset size is incorrect? How???
| 17:21:56 |
aloisw | I'd guess because it forgot to shrink after noticing that the update replaced one entry? | 17:24:59 |
Sergei Zimmerman (xokdvium) | Updates never replace anything - they copy to a new attribute set though. It's puzzling | 17:25:38 |
aloisw | In reply to @raitobezarius:matrix.org i want to go and say that zomg the fact that we broke eval based on this behavior :') Honestly I didn't even know before tracing this down that true is the expected value in this place. | 17:25:58 |
Sergei Zimmerman (xokdvium) | Ah I see, that might be my SNAFU hmmm | 17:26:33 |
aloisw | In reply to @xokdvium:matrix.org Updates never replace anything - they copy to a new attribute set though. It's puzzling "Replace" not in the sense that it's an in-place update, but that the keys overlap. I think it allocates sum of the sizes many entries and then is supposed to shrink if not all were needed due to overlap. | 17:28:12 |
Sergei Zimmerman (xokdvium) | Capacity never actually gets shrunk and size is only incremented when doing a push_back to the bindings. Something looks broken in the ExprOpUpdate::eval code. | 17:35:41 |
aloisw | Weirdly nrOpUpdateValuesCopied is still 2 on my machine. | 17:41:18 |
Sergei Zimmerman (xokdvium) | Ah sorry I was confused omg lol. Don't mind the noise | 17:43:37 |
aloisw | Also it doesn't give false if replacing f by an integer. So it's related to the pointer/function mess. | 17:45:45 |
Sergei Zimmerman (xokdvium) | Yeah so doing this does help:
diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc
index f1ba9e01c..5a5acd6aa 100644
--- a/lix/libexpr/eval.cc
+++ b/lix/libexpr/eval.cc
@@ -2682,6 +2682,7 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
/* Functions are incomparable. */
case nFunction:
+ if (pointerEq()) return true;
return false;
case nExternal:
But I'm not sure about all the consequences :)
| 17:49:35 |
Sergei Zimmerman (xokdvium) | * Yeah so doing this does help:
diff --git a/lix/libexpr/eval.cc b/lix/libexpr/eval.cc
index f1ba9e01c..5a5acd6aa 100644
--- a/lix/libexpr/eval.cc
+++ b/lix/libexpr/eval.cc
@@ -2682,6 +2682,7 @@ bool EvalState::eqValues(Value & v1, Value & v2, const PosIdx pos, std::string_v
/* Functions are incomparable. */
case nFunction:
+ if (pointerEq()) return true;
return false;
case nExternal:
But I'm not sure about all the consequences :)
| 17:49:49 |
Sergei Zimmerman (xokdvium) | * ~~What's even more cursed is this~~:
- xokdvium got confused, don't mind the noise *
| 17:53:14 |
aloisw | let a = { f = x: x; }; in a.f == a.f would now return true. | 17:58:31 |
aloisw | I think https://git.lix.systems/lix-project/lix/commit/80654b84b610f4c0622dd10f0af78a8a2ce97048 is the offending change btw. Currently building that and its parent to confirm. | 18:01:20 |
Sergei Zimmerman (xokdvium) | Worth mentioning on https://gerrit.lix.systems/c/lix/+/4556. But the cat is out of the bag on this and compat with cppnix wasn't a design decision for that patch? | 18:01:28 |
aloisw | In reply to @aloisw:julia0815.de I think https://git.lix.systems/lix-project/lix/commit/80654b84b610f4c0622dd10f0af78a8a2ce97048 is the offending change btw. Currently building that and its parent to confirm. It's not, weirdly enough I get true there? | 18:06:22 |
aloisw | Ah fuck I forgot to change f back to a function. | 18:10:03 |
aloisw | Confirmed this is the breaking change. | 18:12:25 |
raitobezarius | https://gerrit.lix.systems/c/lix/+/4556 | 18:16:23 |
raitobezarius | not totally | 18:16:49 |
raitobezarius | we looked hard and we were not able to disprove our theory that we were enabling more correctness | 18:17:03 |
raitobezarius | like we ran evaluation regression testing and we had no failure but new successes | 18:17:22 |
raitobezarius | after looking hard at the new success, we were unable to say "ah it's wrong", but more like: ah it's possibly a fun eq ptr bug | 18:17:44 |
raitobezarius | put in another way, breaking bug to bug compatibility: yes, by having a behavior that agrees on successes: yes, new failures: not an intended objective | 18:19:11 |