1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-25 10:41:16 +02:00

Throw CachedEvalError if a cached value exists but has type "failed"

Otherwise you get unhelpful errors like

  error: 'apps' is not an attribute set

Fixes #12762.
This commit is contained in:
Eelco Dolstra 2025-03-31 15:03:57 +02:00
parent 3f13cc0f87
commit 8b438fccb4
2 changed files with 23 additions and 14 deletions

View file

@ -418,6 +418,14 @@ Value & AttrCursor::getValue()
return **_value;
}
void AttrCursor::fetchCachedValue()
{
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
if (cachedValue && std::get_if<failed_t>(&cachedValue->second) && parent)
throw CachedEvalError(ref(parent->first), parent->second);
}
std::vector<Symbol> AttrCursor::getAttrPath() const
{
if (parent) {
@ -494,8 +502,7 @@ Suggestions AttrCursor::getSuggestionsForAttr(Symbol name)
std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name)
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
fetchCachedValue();
if (cachedValue) {
if (auto attrs = std::get_if<std::vector<Symbol>>(&cachedValue->second)) {
@ -585,8 +592,7 @@ OrSuggestions<ref<AttrCursor>> AttrCursor::findAlongAttrPath(const std::vector<S
std::string AttrCursor::getString()
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
fetchCachedValue();
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
if (auto s = std::get_if<string_t>(&cachedValue->second)) {
debug("using cached string attribute '%s'", getAttrPathStr());
@ -607,8 +613,7 @@ std::string AttrCursor::getString()
string_t AttrCursor::getStringWithContext()
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
fetchCachedValue();
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
if (auto s = std::get_if<string_t>(&cachedValue->second)) {
bool valid = true;
@ -654,8 +659,7 @@ string_t AttrCursor::getStringWithContext()
bool AttrCursor::getBool()
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
fetchCachedValue();
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
if (auto b = std::get_if<bool>(&cachedValue->second)) {
debug("using cached Boolean attribute '%s'", getAttrPathStr());
@ -676,8 +680,7 @@ bool AttrCursor::getBool()
NixInt AttrCursor::getInt()
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
fetchCachedValue();
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
if (auto i = std::get_if<int_t>(&cachedValue->second)) {
debug("using cached integer attribute '%s'", getAttrPathStr());
@ -698,8 +701,7 @@ NixInt AttrCursor::getInt()
std::vector<std::string> AttrCursor::getListOfStrings()
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
fetchCachedValue();
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
if (auto l = std::get_if<std::vector<std::string>>(&cachedValue->second)) {
debug("using cached list of strings attribute '%s'", getAttrPathStr());
@ -731,8 +733,7 @@ std::vector<std::string> AttrCursor::getListOfStrings()
std::vector<Symbol> AttrCursor::getAttrs()
{
if (root->db) {
if (!cachedValue)
cachedValue = root->db->getAttr(getKey());
fetchCachedValue();
if (cachedValue && !std::get_if<placeholder_t>(&cachedValue->second)) {
if (auto attrs = std::get_if<std::vector<Symbol>>(&cachedValue->second)) {
debug("using cached attrset attribute '%s'", getAttrPathStr());

View file

@ -99,6 +99,14 @@ class AttrCursor : public std::enable_shared_from_this<AttrCursor>
Value & getValue();
/**
* If `cachedValue` is unset, try to initialize it from the
* database. It is not an error if it does not exist. Throw a
* `CachedEvalError` exception if it does exist but has type
* `AttrType::Failed`.
*/
void fetchCachedValue();
public:
AttrCursor(