* In an nested with' where the inner with is a variable (with ...;

with someVar; ...'), the contents of the variable would be
  clobbered.  (The attributes in the outer `with' were added to the
  variable.)
This commit is contained in:
Eelco Dolstra 2010-04-16 13:44:02 +00:00
parent 04c4bd3624
commit 02c1dac909
3 changed files with 15 additions and 7 deletions

View file

@ -649,6 +649,11 @@ void ExprWith::eval(EvalState & state, Env & env, Value & v)
Env * env3 = &env; Env * env3 = &env;
for (unsigned int l = prevWith; l; --l, env3 = env3->up) ; 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) { foreach (Bindings::iterator, i, *env3->values[0].attrs) {
Bindings::iterator j = env2.values[0].attrs->find(i->first); Bindings::iterator j = env2.values[0].attrs->find(i->first);
if (j == env2.values[0].attrs->end()) if (j == env2.values[0].attrs->end())
@ -1042,7 +1047,8 @@ void EvalState::printStats()
printMsg(v, format(" expressions evaluated: %1%") % nrEvaluated); printMsg(v, format(" expressions evaluated: %1%") % nrEvaluated);
printMsg(v, format(" stack space used: %1% bytes") % (&x - deepestStack)); printMsg(v, format(" stack space used: %1% bytes") % (&x - deepestStack));
printMsg(v, format(" max eval() nesting depth: %1%") % maxRecursionDepth); 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)") printMsg(v, format(" environments allocated: %1% (%2% bytes)")
% nrEnvs % (nrEnvs * sizeof(Env))); % nrEnvs % (nrEnvs * sizeof(Env)));
printMsg(v, format(" values allocated in environments: %1% (%2% bytes)") printMsg(v, format(" values allocated in environments: %1% (%2% bytes)")

View file

@ -177,14 +177,15 @@ static void getDerivations(EvalState & state, Value & vIn,
there are names clashes between derivations, the derivation there are names clashes between derivations, the derivation
bound to the attribute with the "lower" name should take bound to the attribute with the "lower" name should take
precedence). */ precedence). */
StringSet attrs; typedef std::map<string, Symbol> SortedSymbols;
SortedSymbols attrs;
foreach (Bindings::iterator, i, *v.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) { foreach (SortedSymbols::iterator, i, attrs) {
startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % *i); startNest(nest, lvlDebug, format("evaluating attribute `%1%'") % i->first);
string pathPrefix2 = addToPath(pathPrefix, *i); string pathPrefix2 = addToPath(pathPrefix, i->first);
Value & v2((*v.attrs)[state.symbols.create(*i)]); Value & v2((*v.attrs)[i->second]);
if (combineChannels) if (combineChannels)
getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done); getDerivations(state, v2, pathPrefix2, autoArgs, drvs, done);
else if (getDerivation(state, v2, pathPrefix2, drvs, done)) { else if (getDerivation(state, v2, pathPrefix2, drvs, done)) {

View file

@ -1089,6 +1089,7 @@ static void opQuery(Globals & globals,
foreach (vector<DrvInfo>::iterator, i, elems2) { foreach (vector<DrvInfo>::iterator, i, elems2) {
try { try {
startNest(nest, lvlDebug, format("outputting query result `%1%'") % i->attrPath);
/* For table output. */ /* For table output. */
Strings columns; Strings columns;