mirror of
https://github.com/NixOS/nix
synced 2025-06-25 02:21:16 +02:00
builtins.warn: Use new EvalBaseError + "evaluation warning"
This commit is contained in:
parent
831d96d8d7
commit
70b1036224
6 changed files with 53 additions and 7 deletions
|
@ -70,6 +70,13 @@ EvalErrorBuilder<T>::addTrace(PosIdx pos, std::string_view formatString, const A
|
|||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
EvalErrorBuilder<T> & EvalErrorBuilder<T>::setIsFromExpr()
|
||||
{
|
||||
error.err.isFromExpr = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void EvalErrorBuilder<T>::debugThrow()
|
||||
{
|
||||
|
@ -85,6 +92,7 @@ void EvalErrorBuilder<T>::debugThrow()
|
|||
throw error;
|
||||
}
|
||||
|
||||
template class EvalErrorBuilder<EvalBaseError>;
|
||||
template class EvalErrorBuilder<EvalError>;
|
||||
template class EvalErrorBuilder<AssertionError>;
|
||||
template class EvalErrorBuilder<ThrownError>;
|
||||
|
|
|
@ -15,27 +15,39 @@ class EvalState;
|
|||
template<class T>
|
||||
class EvalErrorBuilder;
|
||||
|
||||
class EvalError : public Error
|
||||
/**
|
||||
* Base class for all errors that occur during evaluation.
|
||||
*
|
||||
* Most subclasses should inherit from `EvalError` instead of this class.
|
||||
*/
|
||||
class EvalBaseError : public Error
|
||||
{
|
||||
template<class T>
|
||||
friend class EvalErrorBuilder;
|
||||
public:
|
||||
EvalState & state;
|
||||
|
||||
EvalError(EvalState & state, ErrorInfo && errorInfo)
|
||||
EvalBaseError(EvalState & state, ErrorInfo && errorInfo)
|
||||
: Error(errorInfo)
|
||||
, state(state)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
explicit EvalError(EvalState & state, const std::string & formatString, const Args &... formatArgs)
|
||||
explicit EvalBaseError(EvalState & state, const std::string & formatString, const Args &... formatArgs)
|
||||
: Error(formatString, formatArgs...)
|
||||
, state(state)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* `EvalError` is the base class for almost all errors that occur during evaluation.
|
||||
*
|
||||
* All instances of `EvalError` should show a degree of purity that allows them to be
|
||||
* cached in pure mode. This means that they should not depend on the configuration or the overall environment.
|
||||
*/
|
||||
MakeError(EvalError, EvalBaseError);
|
||||
MakeError(ParseError, Error);
|
||||
MakeError(AssertionError, EvalError);
|
||||
MakeError(ThrownError, AssertionError);
|
||||
|
@ -90,6 +102,8 @@ public:
|
|||
|
||||
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> & addTrace(PosIdx pos, HintFmt hint);
|
||||
|
||||
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> & setIsFromExpr();
|
||||
|
||||
template<typename... Args>
|
||||
[[nodiscard, gnu::noinline]] EvalErrorBuilder<T> &
|
||||
addTrace(PosIdx pos, std::string_view formatString, const Args &... formatArgs);
|
||||
|
|
|
@ -806,7 +806,7 @@ static RegisterPrimOp primop_abort({
|
|||
NixStringContext context;
|
||||
auto s = state.coerceToString(pos, *args[0], context,
|
||||
"while evaluating the error message passed to builtins.abort").toOwned();
|
||||
state.error<Abort>("evaluation aborted with the following error message: '%1%'", s).debugThrow();
|
||||
state.error<Abort>("evaluation aborted with the following error message: '%1%'", s).setIsFromExpr().debugThrow();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -825,7 +825,7 @@ static RegisterPrimOp primop_throw({
|
|||
NixStringContext context;
|
||||
auto s = state.coerceToString(pos, *args[0], context,
|
||||
"while evaluating the error message passed to builtin.throw").toOwned();
|
||||
state.error<ThrownError>(s).debugThrow();
|
||||
state.error<ThrownError>(s).setIsFromExpr().debugThrow();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1052,12 +1052,13 @@ static void prim_warn(EvalState & state, const PosIdx pos, Value * * args, Value
|
|||
msg.atPos(state.positions[pos]);
|
||||
auto info = msg.info();
|
||||
info.level = lvlWarn;
|
||||
info.isFromExpr = true;
|
||||
logWarning(info);
|
||||
}
|
||||
|
||||
if (evalSettings.builtinsAbortOnWarn) {
|
||||
// Not an EvalError or subclass, which would cause the error to be stored in the eval cache.
|
||||
state.error<Error>("aborting to reveal stack trace of warning, as abort-on-warn is set").debugThrow();
|
||||
state.error<EvalBaseError>("aborting to reveal stack trace of warning, as abort-on-warn is set").setIsFromExpr().debugThrow();
|
||||
}
|
||||
if (evalSettings.builtinsTraceDebugger || evalSettings.builtinsDebuggerOnWarn) {
|
||||
state.runDebugRepl(nullptr);
|
||||
|
@ -1080,6 +1081,11 @@ static RegisterPrimOp primop_warn({
|
|||
option is set to `true` and the `--debugger` flag is given, the
|
||||
interactive debugger will be started when `warn` is called (like
|
||||
[`break`](@docroot@/language/builtins.md#builtins-break)).
|
||||
|
||||
If the
|
||||
[`abort-on-warn`](@docroot@/command-ref/conf-file.md#conf-abort-on-warn)
|
||||
option is set, the evaluation will be aborted after the warning is printed.
|
||||
This is useful to reveal the stack trace of the warning, when the context is non-interactive and a debugger can not be launched.
|
||||
)",
|
||||
.fun = prim_warn,
|
||||
});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue