From 1daf1babf956cab98857db92de8829a1e7f2ae3e Mon Sep 17 00:00:00 2001 From: pennae Date: Fri, 4 Feb 2022 07:36:56 +0100 Subject: [PATCH] fix nix repl not overriding existing bindings in :a previously :a would override old bindings of a name with new values if the added set contained names that were already bound. in nix 2.6 this doesn't happen any more, which is potentially confusing. fixes #6041 --- src/libexpr/nixexpr.hh | 12 ++++++++---- tests/repl.sh | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/libexpr/nixexpr.hh b/src/libexpr/nixexpr.hh index 4e923ac89..6f6acb074 100644 --- a/src/libexpr/nixexpr.hh +++ b/src/libexpr/nixexpr.hh @@ -367,15 +367,19 @@ struct StaticEnv void sort() { - std::sort(vars.begin(), vars.end(), + std::stable_sort(vars.begin(), vars.end(), [](const Vars::value_type & a, const Vars::value_type & b) { return a.first < b.first; }); } void deduplicate() { - const auto last = std::unique(vars.begin(), vars.end(), - [] (const Vars::value_type & a, const Vars::value_type & b) { return a.first == b.first; }); - vars.erase(last, vars.end()); + auto it = vars.begin(), jt = it, end = vars.end(); + while (jt != end) { + *it = *jt++; + while (jt != end && it->first == jt->first) *it = *jt++; + it++; + } + vars.erase(it, end); } Vars::const_iterator find(const Symbol & name) const diff --git a/tests/repl.sh b/tests/repl.sh index 0e23a98db..6505f1741 100644 --- a/tests/repl.sh +++ b/tests/repl.sh @@ -40,3 +40,26 @@ testRepl () { testRepl # Same thing (kind-of), but with a remote store. testRepl --store "$TEST_ROOT/store?real=$NIX_STORE_DIR" + +testReplResponse () { + local response="$(nix repl <<< "$1")" + echo "$response" | grep -qs "$2" \ + || fail "repl command set: + +$1 + +does not respond with: + +$2 + +but with: + +$response" +} + +# :a uses the newest version of a symbol +testReplResponse ' +:a { a = "1"; } +:a { a = "2"; } +"result: ${a}" +' "result: 2"