aboutsummaryrefslogtreecommitdiff
path: root/src/libexpr/eval-cache.cc
diff options
context:
space:
mode:
authoreldritch horrors <pennae@lix.systems>2024-03-08 07:09:48 +0100
committereldritch horrors <pennae@lix.systems>2024-03-09 04:47:05 -0700
commit08252967a8c2ab15f3fb8bdfb848f007d4032d50 (patch)
tree909ec8357654d4d179f0f8e7dfc5d3d623256b46 /src/libexpr/eval-cache.cc
parentd4c738fe4c587c3f09b0fda899f419f2de97ee2f (diff)
libexpr: Support structured error classes
While preparing PRs like #9753, I've had to change error messages in dozens of code paths. It would be nice if instead of EvalError("expected 'boolean' but found '%1%'", showType(v)) we could write TypeError(v, "boolean") or similar. Then, changing the error message could be a mechanical refactor with the compiler pointing out places the constructor needs to be changed, rather than the error-prone process of grepping through the codebase. Structured errors would also help prevent the "same" error from having multiple slightly different messages, and could be a first step towards error codes / an error index. This PR reworks the exception infrastructure in `libexpr` to support exception types with different constructor signatures than `BaseError`. Actually refactoring the exceptions to use structured data will come in a future PR (this one is big enough already, as it has to touch every exception in `libexpr`). The core design is in `eval-error.hh`. Generally, errors like this: state.error("'%s' is not a string", getAttrPathStr()) .debugThrow<TypeError>() are transformed like this: state.error<TypeError>("'%s' is not a string", getAttrPathStr()) .debugThrow() The type annotation has moved from `ErrorBuilder::debugThrow` to `EvalState::error`. (cherry picked from commit c6a89c1a1659b31694c0fbcd21d78a6dd521c732) Change-Id: Iced91ba4e00ca9e801518071fb43798936cbd05a
Diffstat (limited to 'src/libexpr/eval-cache.cc')
-rw-r--r--src/libexpr/eval-cache.cc30
1 files changed, 15 insertions, 15 deletions
diff --git a/src/libexpr/eval-cache.cc b/src/libexpr/eval-cache.cc
index 2c9aa5532..20dd9e0bc 100644
--- a/src/libexpr/eval-cache.cc
+++ b/src/libexpr/eval-cache.cc
@@ -490,7 +490,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
if (forceErrors)
debug("reevaluating failed cached attribute '%s'", getAttrPathStr(name));
else
- throw CachedEvalError("cached failure of attribute '%s'", getAttrPathStr(name));
+ throw CachedEvalError(root->state, "cached failure of attribute '%s'", getAttrPathStr(name));
} else
return std::make_shared<AttrCursor>(root,
std::make_pair(shared_from_this(), name), nullptr, std::move(attr));
@@ -499,7 +499,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
// evaluate to see whether 'name' exists
} else
return nullptr;
- //throw TypeError("'%s' is not an attribute set", getAttrPathStr());
+ //error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
}
}
@@ -507,7 +507,7 @@ std::shared_ptr<AttrCursor> AttrCursor::maybeGetAttr(Symbol name, bool forceErro
if (v.type() != nAttrs)
return nullptr;
- //throw TypeError("'%s' is not an attribute set", getAttrPathStr());
+ //error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
auto attr = v.attrs->get(name);
@@ -573,14 +573,14 @@ std::string AttrCursor::getString()
debug("using cached string attribute '%s'", getAttrPathStr());
return s->first;
} else
- root->state.error("'%s' is not a string", getAttrPathStr()).debugThrow<TypeError>();
+ root->state.error<TypeError>("'%s' is not a string", getAttrPathStr()).debugThrow();
}
}
auto & v = forceValue();
if (v.type() != nString && v.type() != nPath)
- root->state.error("'%s' is not a string but %s", getAttrPathStr()).debugThrow<TypeError>();
+ root->state.error<TypeError>("'%s' is not a string but %s", getAttrPathStr()).debugThrow();
return v.type() == nString ? v.string.s : v.path().to_string();
}
@@ -615,7 +615,7 @@ string_t AttrCursor::getStringWithContext()
return *s;
}
} else
- root->state.error("'%s' is not a string", getAttrPathStr()).debugThrow<TypeError>();
+ root->state.error<TypeError>("'%s' is not a string", getAttrPathStr()).debugThrow();
}
}
@@ -629,7 +629,7 @@ string_t AttrCursor::getStringWithContext()
else if (v.type() == nPath)
return {v.path().to_string(), {}};
else
- root->state.error("'%s' is not a string but %s", getAttrPathStr()).debugThrow<TypeError>();
+ root->state.error<TypeError>("'%s' is not a string but %s", getAttrPathStr()).debugThrow();
}
bool AttrCursor::getBool()
@@ -642,14 +642,14 @@ bool AttrCursor::getBool()
debug("using cached Boolean attribute '%s'", getAttrPathStr());
return *b;
} else
- root->state.error("'%s' is not a Boolean", getAttrPathStr()).debugThrow<TypeError>();
+ root->state.error<TypeError>("'%s' is not a Boolean", getAttrPathStr()).debugThrow();
}
}
auto & v = forceValue();
if (v.type() != nBool)
- root->state.error("'%s' is not a Boolean", getAttrPathStr()).debugThrow<TypeError>();
+ root->state.error<TypeError>("'%s' is not a Boolean", getAttrPathStr()).debugThrow();
return v.boolean;
}
@@ -664,14 +664,14 @@ NixInt AttrCursor::getInt()
debug("using cached integer attribute '%s'", getAttrPathStr());
return i->x;
} else
- throw TypeError("'%s' is not an integer", getAttrPathStr());
+ root->state.error<TypeError>("'%s' is not an integer", getAttrPathStr()).debugThrow();
}
}
auto & v = forceValue();
if (v.type() != nInt)
- throw TypeError("'%s' is not an integer", getAttrPathStr());
+ root->state.error<TypeError>("'%s' is not an integer", getAttrPathStr()).debugThrow();
return v.integer;
}
@@ -686,7 +686,7 @@ std::vector<std::string> AttrCursor::getListOfStrings()
debug("using cached list of strings attribute '%s'", getAttrPathStr());
return *l;
} else
- throw TypeError("'%s' is not a list of strings", getAttrPathStr());
+ root->state.error<TypeError>("'%s' is not a list of strings", getAttrPathStr()).debugThrow();
}
}
@@ -696,7 +696,7 @@ std::vector<std::string> AttrCursor::getListOfStrings()
root->state.forceValue(v, noPos);
if (v.type() != nList)
- throw TypeError("'%s' is not a list", getAttrPathStr());
+ root->state.error<TypeError>("'%s' is not a list", getAttrPathStr()).debugThrow();
std::vector<std::string> res;
@@ -719,14 +719,14 @@ std::vector<Symbol> AttrCursor::getAttrs()
debug("using cached attrset attribute '%s'", getAttrPathStr());
return *attrs;
} else
- root->state.error("'%s' is not an attribute set", getAttrPathStr()).debugThrow<TypeError>();
+ root->state.error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
}
}
auto & v = forceValue();
if (v.type() != nAttrs)
- root->state.error("'%s' is not an attribute set", getAttrPathStr()).debugThrow<TypeError>();
+ root->state.error<TypeError>("'%s' is not an attribute set", getAttrPathStr()).debugThrow();
std::vector<Symbol> attrs;
for (auto & attr : *getValue().attrs)