diff options
Diffstat (limited to 'src/libexpr')
-rw-r--r-- | src/libexpr/eval.cc | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index f1212cd22542..43d8f1399e09 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -1183,17 +1183,28 @@ void ExprPos::eval(EvalState & state, Env & env, Value & v) void EvalState::forceValueDeep(Value & v) { - forceValue(v); + std::set<const Value *> seen; - if (v.type == tAttrs) { - foreach (Bindings::iterator, i, *v.attrs) - forceValueDeep(*i->value); - } + std::function<void(Value & v)> recurse; - else if (v.type == tList) { - for (unsigned int n = 0; n < v.list.length; ++n) - forceValueDeep(*v.list.elems[n]); - } + recurse = [&](Value & v) { + if (seen.find(&v) != seen.end()) return; + seen.insert(&v); + + forceValue(v); + + if (v.type == tAttrs) { + foreach (Bindings::iterator, i, *v.attrs) + recurse(*i->value); + } + + else if (v.type == tList) { + for (unsigned int n = 0; n < v.list.length; ++n) + recurse(*v.list.elems[n]); + } + }; + + recurse(v); } |