always re-eval cached failures

This is terrible UX, and frankly an eval failure should be a cache
invalidation anyway.

This removes the CachedEvalError type entirely.

Fixes #223.

Change-Id: I91f8003eabd0ea45003024e96d1de3c7ae8e49d8
This commit is contained in:
Qyriad 2024-04-04 10:46:44 -06:00 committed by jade
parent b47c159aec
commit a4ef195a9f
5 changed files with 18 additions and 15 deletions

View file

@ -0,0 +1,8 @@
---
synopsis: re-evaluate cached evaluation errors
cls: 771
---
"cached failure of [expr]" errors have been removed: expressions already in the
eval cache as a failure will now simply be re-evaluated, removing the need to
set `--no-eval-cache` or similar to see the error.

View file

@ -469,7 +469,7 @@ Suggestions AttrCursor::getSuggestionsForAttr(Symbol name)
return Suggestions::bestMatches(strAttrNames, root->state.symbols[name]); return Suggestions::bestMatches(strAttrNames, root->state.symbols[name]);
} }
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErrors) std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
{ {
if (root->db) { if (root->db) {
if (!cachedValue) if (!cachedValue)
@ -487,10 +487,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
if (std::get_if<missing_t>(&attr->second)) if (std::get_if<missing_t>(&attr->second))
return nullptr; return nullptr;
else if (std::get_if<failed_t>(&attr->second)) { else if (std::get_if<failed_t>(&attr->second)) {
if (forceErrors)
debug("reevaluating failed cached attribute '%s'", getAttrPathStr(name)); debug("reevaluating failed cached attribute '%s'", getAttrPathStr(name));
else
throw CachedEvalError(root->state, "cached failure of attribute '%s'", getAttrPathStr(name));
} else } else
return std::make_shared<AttrCursor>(root, return std::make_shared<AttrCursor>(root,
std::make_pair(shared_from_this(), name), nullptr, std::move(attr)); std::make_pair(shared_from_this(), name), nullptr, std::move(attr));
@ -536,9 +533,9 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(std::string_view name)
return maybeGetAttr(root->state.symbols.create(name)); return maybeGetAttr(root->state.symbols.create(name));
} }
ref<AttrCursor> AttrCursor::getAttr(Symbol name, bool forceErrors) ref<AttrCursor> AttrCursor::getAttr(Symbol name)
{ {
auto p = maybeGetAttr(name, forceErrors); auto p = maybeGetAttr(name);
if (!p) if (!p)
throw Error("attribute '%s' does not exist", getAttrPathStr(name)); throw Error("attribute '%s' does not exist", getAttrPathStr(name));
return ref(p); return ref(p);
@ -549,11 +546,11 @@ ref<AttrCursor> AttrCursor::getAttr(std::string_view name)
return getAttr(root->state.symbols.create(name)); return getAttr(root->state.symbols.create(name));
} }
OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force) OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<Symbol> & attrPath)
{ {
auto res = shared_from_this(); auto res = shared_from_this();
for (auto & attr : attrPath) { for (auto & attr : attrPath) {
auto child = res->maybeGetAttr(attr, force); auto child = res->maybeGetAttr(attr);
if (!child) { if (!child) {
auto suggestions = res->getSuggestionsForAttr(attr); auto suggestions = res->getSuggestionsForAttr(attr);
return OrSuggestions<ref<AttrCursor>>::failed(suggestions); return OrSuggestions<ref<AttrCursor>>::failed(suggestions);
@ -750,7 +747,7 @@ bool AttrCursor::isDerivation()
StorePath AttrCursor::forceDerivation() StorePath AttrCursor::forceDerivation()
{ {
auto aDrvPath = getAttr(root->state.sDrvPath, true); auto aDrvPath = getAttr(root->state.sDrvPath);
auto drvPath = root->state.store->parseStorePath(aDrvPath->getString()); auto drvPath = root->state.store->parseStorePath(aDrvPath->getString());
if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) { if (!root->state.store->isValidPath(drvPath) && !settings.readOnlyMode) {
/* The eval cache contains 'drvPath', but the actual path has /* The eval cache contains 'drvPath', but the actual path has

View file

@ -100,11 +100,11 @@ public:
Suggestions getSuggestionsForAttr(Symbol name); Suggestions getSuggestionsForAttr(Symbol name);
std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name, bool forceErrors = false); std::shared_ptr<AttrCursor> maybeGetAttr(Symbol name);
std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name); std::shared_ptr<AttrCursor> maybeGetAttr(std::string_view name);
ref<AttrCursor> getAttr(Symbol name, bool forceErrors = false); ref<AttrCursor> getAttr(Symbol name);
ref<AttrCursor> getAttr(std::string_view name); ref<AttrCursor> getAttr(std::string_view name);
@ -112,7 +112,7 @@ public:
* Get an attribute along a chain of attrsets. Note that this does * Get an attribute along a chain of attrsets. Note that this does
* not auto-call functors or functions. * not auto-call functors or functions.
*/ */
OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath, bool force = false); OrSuggestions<ref<AttrCursor>> findAlongAttrPath(const std::vector<Symbol> & attrPath);
std::string getString(); std::string getString();

View file

@ -99,7 +99,6 @@ template class EvalErrorBuilder<TypeError>;
template class EvalErrorBuilder<UndefinedVarError>; template class EvalErrorBuilder<UndefinedVarError>;
template class EvalErrorBuilder<MissingArgumentError>; template class EvalErrorBuilder<MissingArgumentError>;
template class EvalErrorBuilder<InfiniteRecursionError>; template class EvalErrorBuilder<InfiniteRecursionError>;
template class EvalErrorBuilder<CachedEvalError>;
template class EvalErrorBuilder<InvalidPathError>; template class EvalErrorBuilder<InvalidPathError>;
} }

View file

@ -44,7 +44,6 @@ MakeError(TypeError, EvalError);
MakeError(UndefinedVarError, EvalError); MakeError(UndefinedVarError, EvalError);
MakeError(MissingArgumentError, EvalError); MakeError(MissingArgumentError, EvalError);
MakeError(RestrictedPathError, Error); MakeError(RestrictedPathError, Error);
MakeError(CachedEvalError, EvalError);
MakeError(InfiniteRecursionError, EvalError); MakeError(InfiniteRecursionError, EvalError);
struct InvalidPathError : public EvalError struct InvalidPathError : public EvalError