libexpr: move realiseContext back to EvalState

throwing debuggable errors is effectively never-async, and realising a
context requires acquiring a context first, i.e. evaluating something.
since realiseContext is only used by primops the effect is very minor.

Change-Id: I73b3b277188700e5cdf6f30599fb6674ec1ab753
This commit is contained in:
eldritch horrors
2025-03-25 20:14:45 +01:00
parent 0ff8c2b06f
commit d2f4b4042d
3 changed files with 40 additions and 49 deletions
+2 -3
View File
@@ -280,12 +280,10 @@ EvalBuiltins::EvalBuiltins(
EvalPaths::EvalPaths(
AsyncIoRoot & aio,
const ref<Store> & store,
const ref<Store> buildStore,
SearchPath searchPath,
EvalErrorContext & errors
)
: store(store)
, buildStore(buildStore)
, searchPath_(std::move(searchPath))
, errors(errors)
{
@@ -321,7 +319,7 @@ Evaluator::Evaluator(
std::function<ReplExitStatus(EvalState & es, ValMap const & extraEnv)> debugRepl
)
: s(symbols)
, paths(aio, store, buildStore ? ref(buildStore) : store, [&] {
, paths(aio, store, [&] {
SearchPath searchPath;
if (!evalSettings.pureEval) {
for (auto & i : _searchPath.elements)
@@ -334,6 +332,7 @@ Evaluator::Evaluator(
, builtins(mem, symbols, paths.searchPath(), store->config().storeDir)
, repair(NoRepair)
, store(store)
, buildStore(buildStore ? ref(buildStore) : store)
, debug{
debugRepl ? std::make_unique<DebugState>(
positions,
+11 -11
View File
@@ -365,10 +365,6 @@ struct EvalErrorContext
class EvalPaths
{
ref<Store> store;
/**
* Store used to build stuff.
*/
ref<Store> buildStore;
SearchPath searchPath_;
EvalErrorContext & errors;
@@ -376,7 +372,6 @@ public:
EvalPaths(
AsyncIoRoot & aio,
const ref<Store> & store,
const ref<Store> buildStore,
SearchPath searchPath,
EvalErrorContext & errors
);
@@ -484,12 +479,6 @@ public:
* single `NixStringContextElem::Opaque` element of that store path.
*/
void mkStorePathString(const StorePath & storePath, Value & v);
/**
* Realise the given context, and return a mapping from the placeholders
* used to construct the associated value to their final store path
*/
[[nodiscard]] kj::Promise<Result<StringMap>> realiseContext(const NixStringContext & context);
};
struct EvalStatistics
@@ -540,6 +529,11 @@ public:
*/
const ref<Store> store;
/**
* Store used to build stuff.
*/
ref<Store> buildStore;
std::unique_ptr<DebugState> debug;
EvalErrorContext errors;
@@ -713,6 +707,12 @@ public:
std::string_view forceString(Value & v, NixStringContext & context, const PosIdx pos, std::string_view errorCtx);
std::string_view forceStringNoCtx(Value & v, const PosIdx pos, std::string_view errorCtx);
/**
* Realise the given context, and return a mapping from the placeholders
* used to construct the associated value to their final store path
*/
[[nodiscard]] StringMap realiseContext(const NixStringContext & context);
public:
/**
* @return true iff the value `v` denotes a derivation (i.e. a
+27 -35
View File
@@ -42,23 +42,17 @@ namespace nix {
* Miscellaneous
*************************************************************/
kj::Promise<Result<StringMap>> EvalPaths::realiseContext(const NixStringContext & context)
try {
StringMap EvalState::realiseContext(const NixStringContext & context)
{
std::vector<DerivedPath::Built> drvs;
StringMap res;
for (auto & c : context) {
// NOLINTNEXTLINE(cppcoreguidelines-avoid-capturing-lambda-coroutines)
auto ensureValid = [&](const StorePath & p) -> kj::Promise<Result<void>> {
try {
if (!TRY_AWAIT(store->isValidPath(p)))
errors.make<InvalidPathError>(store->printStorePath(p)).debugThrow();
co_return result::success();
} catch (...) {
co_return result::current_exception();
}
auto ensureValid = [&](const StorePath & p) {
if (!aio.blockOn(ctx.store->isValidPath(p)))
ctx.errors.make<InvalidPathError>(ctx.store->printStorePath(p)).debugThrow();
};
TRY_AWAIT(std::visit(overloaded {
std::visit(overloaded {
[&](const NixStringContextElem::Built & b) {
drvs.push_back(DerivedPath::Built {
.drvPath = b.drvPath,
@@ -67,36 +61,36 @@ try {
return ensureValid(b.drvPath->getBaseStorePath());
},
[&](const NixStringContextElem::Opaque & o) {
auto ctxS = store->printStorePath(o.path);
auto ctxS = ctx.store->printStorePath(o.path);
res.insert_or_assign(ctxS, ctxS);
return ensureValid(o.path);
},
[&](const NixStringContextElem::DrvDeep & d) {
/* Treat same as Opaque */
auto ctxS = store->printStorePath(d.drvPath);
auto ctxS = ctx.store->printStorePath(d.drvPath);
res.insert_or_assign(ctxS, ctxS);
return ensureValid(d.drvPath);
},
}, c.raw));
}, c.raw);
}
if (drvs.empty()) co_return StringMap{};
if (drvs.empty()) return StringMap{};
if (!evalSettings.enableImportFromDerivation)
errors.make<EvalError>(
ctx.errors.make<EvalError>(
"cannot build '%1%' during evaluation because the option 'allow-import-from-derivation' is disabled",
drvs.begin()->to_string(*store)
drvs.begin()->to_string(*ctx.store)
).debugThrow();
/* Build/substitute the context. */
std::vector<DerivedPath> buildReqs;
for (auto & d : drvs) buildReqs.emplace_back(DerivedPath { d });
TRY_AWAIT(buildStore->buildPaths(buildReqs, bmNormal, store));
aio.blockOn(ctx.buildStore->buildPaths(buildReqs, bmNormal, ctx.store));
StorePathSet outputsToCopyAndAllow;
for (auto & drv : drvs) {
auto outputs = TRY_AWAIT(resolveDerivedPath(*buildStore, drv, &*store));
auto outputs = aio.blockOn(resolveDerivedPath(*ctx.buildStore, drv, &*ctx.store));
for (auto & [outputName, outputPath] : outputs) {
outputsToCopyAndAllow.insert(outputPath);
@@ -108,24 +102,22 @@ try {
.drvPath = drv.drvPath,
.output = outputName,
}).render(),
buildStore->printStorePath(outputPath)
ctx.buildStore->printStorePath(outputPath)
);
}
}
}
if (store != buildStore) TRY_AWAIT(copyClosure(*buildStore, *store, outputsToCopyAndAllow));
if (allowedPaths) {
for (auto & outputPath : outputsToCopyAndAllow) {
/* Add the output of this derivations to the allowed
paths. */
allowPath(outputPath);
}
if (ctx.store != ctx.buildStore) {
aio.blockOn(copyClosure(*ctx.buildStore, *ctx.store, outputsToCopyAndAllow));
}
for (auto & outputPath : outputsToCopyAndAllow) {
/* Add the output of this derivations to the allowed
paths. */
ctx.paths.allowPath(outputPath);
}
co_return res;
} catch (...) {
co_return result::current_exception();
return res;
}
static auto realisePath(EvalState & state, const PosIdx pos, Value & v, auto checkFn)
@@ -135,7 +127,7 @@ static auto realisePath(EvalState & state, const PosIdx pos, Value & v, auto che
auto path = state.coerceToPath(noPos, v, context, "while realising the context of a path");
try {
StringMap rewrites = state.aio.blockOn(state.ctx.paths.realiseContext(context));
StringMap rewrites = state.realiseContext(context);
return checkFn(SourcePath(CanonPath(
state.ctx.paths.toRealPath(rewriteStrings(path.canonical().abs(), rewrites), context)
@@ -332,7 +324,7 @@ void prim_exec(EvalState & state, const PosIdx pos, Value * * args, Value & v)
false, false).toOwned());
}
try {
auto _ = state.aio.blockOn(state.ctx.paths.realiseContext(context)); // FIXME: Handle CA derivations
auto _ = state.realiseContext(context); // FIXME: Handle CA derivations
} catch (InvalidPathError & e) {
e.addTrace(state.ctx.positions[pos], "while realising the context for builtins.exec");
throw;
@@ -1328,7 +1320,7 @@ static void prim_findFile(EvalState & state, const PosIdx pos, Value * * args, V
false, false).toOwned();
try {
auto rewrites = state.aio.blockOn(state.ctx.paths.realiseContext(context));
auto rewrites = state.realiseContext(context);
path = rewriteStrings(path, rewrites);
} catch (InvalidPathError & e) {
state.ctx.errors.make<EvalError>(
@@ -1520,7 +1512,7 @@ static void addPath(
try {
// FIXME: handle CA derivation outputs (where path needs to
// be rewritten to the actual output).
auto rewrites = state.aio.blockOn(state.ctx.paths.realiseContext(context));
auto rewrites = state.realiseContext(context);
path = rewriteStrings(path, rewrites);
Path realPath = path;