about summary refs log tree commit diff
path: root/src/libexpr
diff options
context:
space:
mode:
Diffstat (limited to 'src/libexpr')
-rw-r--r--src/libexpr/eval.cc8
-rw-r--r--src/libexpr/get-drvs.cc13
2 files changed, 14 insertions, 7 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 69e7bd8b3c..ac475c8931 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -649,6 +649,11 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
         Env * env3 = &env;
         for (unsigned int l = prevWith; l; --l, env3 = env3->up) ;
 
+        /* Because the first `with' may be a shallow copy of another
+           attribute set (through a tCopy node), we need to clone its
+           `attrs' before modifying them. */
+        env2.values[0].attrs = new Bindings(*env2.values[0].attrs);
+
         foreach (Bindings::iterator, i, *env3->values[0].attrs) {
             Bindings::iterator j = env2.values[0].attrs->find(i->first);
             if (j == env2.values[0].attrs->end())
@@ -1042,7 +1047,8 @@ void EvalState::printStats()
     printMsg(v, format("  expressions evaluated: %1%") % nrEvaluated);
     printMsg(v, format("  stack space used: %1% bytes") % (&x - deepestStack));
     printMsg(v, format("  max eval() nesting depth: %1%") % maxRecursionDepth);
-    printMsg(v, format("  stack space per eval() level: %1% bytes") % ((&x - deepestStack) / (float) maxRecursionDepth));
+    printMsg(v, format("  stack space per eval() level: %1% bytes")
+        % ((&x - deepestStack) / (float) maxRecursionDepth));
     printMsg(v, format("  environments allocated: %1% (%2% bytes)")
         % nrEnvs % (nrEnvs * sizeof(Env)));
     printMsg(v, format("  values allocated in environments: %1% (%2% bytes)")
diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc
index 6964e3e3b7..8af011d549 100644
--- a/src/libexpr/get-drvs.cc
+++ b/src/libexpr/get-drvs.cc
@@ -177,14 +177,15 @@ static void getDerivations(EvalState & state, Value & vIn,
            there are names clashes between derivations, the derivation
            bound to the attribute with the "lower" name should take
            precedence). */
-        StringSet attrs;
+        typedef std::map<string, Symbol> SortedSymbols;
+        SortedSymbols attrs;
         foreach (Bindings::iterator, i, *v.attrs)
-            attrs.insert(i->first);
+            attrs.insert(std::pair<string, Symbol>(i->first, i->first));
 
-        foreach (StringSet::iterator, i, attrs) {
-            startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % *i);
-            string pathPrefix2 = addToPath(pathPrefix, *i);
-            Value & v2((*v.attrs)[state.symbols.create(*i)]);
+        foreach (SortedSymbols::iterator, i, attrs) {
+            startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first);
+            string pathPrefix2 = addToPath(pathPrefix, i->first);
+            Value & v2((*v.attrs)[i->second]);
             if (combineChannels)
                 getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done);
             else if (getDerivation(state, v2, pathPrefix2, drvs, done)) {