1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-20 09:19:36 +01:00

Make lazyGetAttrField return something more informative

This commit is contained in:
regnat 2021-06-09 18:39:55 +02:00
parent 8d2be51d19
commit af775bdcf9
5 changed files with 21 additions and 11 deletions

View file

@ -438,7 +438,7 @@ Value * InstallableFlake::getFlakeOutputs(EvalState & state, const flake::Locked
auto vRes = state.allocValue(); auto vRes = state.allocValue();
auto gotField = state.lazyGetAttrField(*vFlake, {state.symbols.create("outputs")}, noPos, *vRes); auto gotField = state.lazyGetAttrField(*vFlake, {state.symbols.create("outputs")}, noPos, *vRes);
assert(gotField); assert(gotField != EvalState::LazyValueType::Missing);
return vRes; return vRes;
} }

View file

@ -68,7 +68,7 @@ std::pair<Value *, Pos> findAlongAttrPath(EvalState & state, const string & attr
throw Error("empty attribute name in selection path '%1%'", attrPath); throw Error("empty attribute name in selection path '%1%'", attrPath);
auto v2 = state.allocValue(); auto v2 = state.allocValue();
auto gotField = state.lazyGetAttrField(*v, {state.symbols.create(attr)}, pos, *v2); auto gotField = state.lazyGetAttrField(*v, {state.symbols.create(attr)}, pos, *v2) != EvalState::LazyValueType::Missing;
if (!gotField) if (!gotField)
throw AttrPathNotFound("attribute '%1%' in selection path '%2%' not found", attr, attrPath); throw AttrPathNotFound("attribute '%1%' in selection path '%2%' not found", attr, attrPath);
v = v2; v = v2;

View file

@ -1189,7 +1189,7 @@ void EvalState::updateCacheStats(ValueCache::CacheResult cacheResult)
}; };
} }
bool EvalState::lazyGetAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest) EvalState::LazyValueType EvalState::lazyGetAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest)
{ {
auto eval_cache = attrs.getEvalCache(); auto eval_cache = attrs.getEvalCache();
if (eval_cache.isEmpty()) { if (eval_cache.isEmpty()) {
@ -1201,8 +1201,8 @@ bool EvalState::lazyGetAttrField(Value & attrs, const std::vector<Symbol> & sele
switch (cacheResult.returnCode) { switch (cacheResult.returnCode) {
case ValueCache::CacheHit: case ValueCache::CacheHit:
if (cacheResult.lastQueriedSymbolIfMissing) if (cacheResult.lastQueriedSymbolIfMissing)
return false; return LazyValueType::Missing;
return true; return LazyValueType::PlainValue;
case ValueCache::Forward: { case ValueCache::Forward: {
auto recordAsVar = new ExprCastedVar(&attrs); auto recordAsVar = new ExprCastedVar(&attrs);
auto accessExpr = new ExprSelect(pos, recordAsVar, selector); auto accessExpr = new ExprSelect(pos, recordAsVar, selector);
@ -1214,11 +1214,13 @@ bool EvalState::lazyGetAttrField(Value & attrs, const std::vector<Symbol> & sele
thunk, thunk,
new ValueCache(resultingCursor) new ValueCache(resultingCursor)
); );
return true; return LazyValueType::DelayedAttrSet;
} }
default: default:
return getAttrField(attrs, selector, pos, dest); if(getAttrField(attrs, selector, pos, dest))
; return LazyValueType::PlainValue;
else
return LazyValueType::Missing;
} }
} }
@ -1308,7 +1310,7 @@ std::vector<Attr> EvalState::getFields(Value & attrs, const Pos & pos)
for (auto & attrName : *attrNames) { for (auto & attrName : *attrNames) {
auto newValue = allocValue(); auto newValue = allocValue();
try { try {
if (lazyGetAttrField(attrs, {attrName}, pos, *newValue)) { if (lazyGetAttrField(attrs, {attrName}, pos, *newValue) != LazyValueType::Missing) {
res.push_back(Attr(attrName, newValue)); res.push_back(Attr(attrName, newValue));
} else { } else {
everythingCached = false; everythingCached = false;

View file

@ -356,9 +356,16 @@ private:
public: public:
bool getAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest); bool getAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest);
enum struct LazyValueType {
PlainValue,
DelayedAttrSet,
Missing,
};
// Similar to `getAttrField`, but if the cache says that the result is an // Similar to `getAttrField`, but if the cache says that the result is an
// attribute set, just return a thunk to it rather than forcing it. // attribute set, just return a thunk to it rather than forcing it.
bool lazyGetAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest); LazyValueType lazyGetAttrField(Value & attrs, const std::vector<Symbol> & selector, const Pos & pos, Value & dest);
// Similar to `getAttrField`, but throws an `Error` if the field cant be // Similar to `getAttrField`, but throws an `Error` if the field cant be
// found // found

View file

@ -154,7 +154,8 @@ struct CmdSearch : InstallableCommand, MixJSON
recurse(); recurse();
else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) { else if (attrPath[0] == "legacyPackages" && attrPath.size() > 2) {
auto hasRecurse = state->getAttrField(current, {state->sRecurseForDerivations}, noPos, *vTmp); auto recurseFieldInfo = state->lazyGetAttrField(current, {state->sRecurseForDerivations}, noPos, *vTmp);
auto hasRecurse = recurseFieldInfo == EvalState::LazyValueType::PlainValue;
if (hasRecurse && state->forceBool(*vTmp, noPos)) if (hasRecurse && state->forceBool(*vTmp, noPos))
recurse(); recurse();
} }