Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
error.hh
Go to the documentation of this file.
1#pragma once
17
18#include "lix/libutil/json-fwd.hh"
20#include "lix/libutil/fmt.hh"
21
22#include <cstring>
23#include <exception>
24#include <list>
25#include <memory>
26#include <optional>
27
28#include <source_location>
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32#include <system_error>
33#include <type_traits>
34
35namespace nix {
36
37
38typedef enum {
39 lvlError = 0,
40 lvlWarn,
41 lvlNotice,
42 lvlInfo,
43 lvlTalkative,
44 lvlChatty,
45 lvlDebug,
46 lvlVomit
47} Verbosity;
48
49template<>
50struct json::is_integral_enum<Verbosity> : std::true_type {};
51
52Verbosity verbosityFromIntClamped(int val);
53
58 std::optional<std::string> prevLineOfCode;
59 std::optional<std::string> errLineOfCode;
60 std::optional<std::string> nextLineOfCode;
61};
62
63struct Pos;
64
65void printCodeLines(std::ostream & out,
66 const std::string & prefix,
67 const Pos & errPos,
68 const LinesOfCode & loc);
69
70struct Trace {
71 std::shared_ptr<Pos> pos;
72 HintFmt hint;
73};
74
75inline bool operator<(const Trace& lhs, const Trace& rhs);
76inline bool operator> (const Trace& lhs, const Trace& rhs);
77inline bool operator<=(const Trace& lhs, const Trace& rhs);
78inline bool operator>=(const Trace& lhs, const Trace& rhs);
79
80struct ErrorInfo {
81 Verbosity level = Verbosity::lvlError;
82 HintFmt msg;
83 std::shared_ptr<Pos> pos;
84 std::list<Trace> traces = {};
85
89 unsigned int status = 1;
90
91 Suggestions suggestions = {};
92
93 static std::optional<std::string> programName;
94};
95
96std::ostream & showErrorInfo(std::ostream & out, const ErrorInfo & einfo, bool showTrace);
97
102class BaseException : public std::exception
103{
104public:
106 {
107 std::source_location location;
108 std::optional<std::string> description;
109 };
110
111private:
117 std::shared_ptr<std::list<AsyncTraceFrame>> _asyncTrace;
118
119public:
120 std::shared_ptr<const std::list<AsyncTraceFrame>> asyncTrace() const
121 {
122 return _asyncTrace;
123 }
124
125 void
126 addAsyncTrace(std::source_location loc, std::optional<std::string> description = std::nullopt)
127 {
128 if (!_asyncTrace) {
129 _asyncTrace = std::make_shared<std::list<AsyncTraceFrame>>();
130 }
131 _asyncTrace->push_back(AsyncTraceFrame{loc, std::move(description)});
132 }
133};
134
139class BaseError : public BaseException
140{
141protected:
142 mutable ErrorInfo err;
143
147 mutable std::optional<std::string> what_;
151 const std::string & calcWhat() const;
152
153public:
154 BaseError(const BaseError &) = default;
155
156 BaseError & operator=(BaseError const & rhs) = default;
157
158 template<typename... Args>
159 BaseError(unsigned int status, const Args & ... args)
160 : err { .level = lvlError, .msg = HintFmt(args...), .status = status }
161 { }
162
163 template<typename... Args>
164 explicit BaseError(const std::string & fs, const Args & ... args)
165 : err { .level = lvlError, .msg = HintFmt(fs, args...) }
166 { }
167
168 template<typename... Args>
169 BaseError(const Suggestions & sug, const Args & ... args)
170 : err { .level = lvlError, .msg = HintFmt(args...), .suggestions = sug }
171 { }
172
173 BaseError(HintFmt hint)
174 : err { .level = lvlError, .msg = hint }
175 { }
176
177 BaseError(ErrorInfo && e)
178 : err(std::move(e))
179 { }
180
181 BaseError(const ErrorInfo & e)
182 : err(e)
183 { }
184
185 const char * what() const noexcept override { return calcWhat().c_str(); }
186 const std::string & msg() const { return calcWhat(); }
187 const ErrorInfo & info() const { calcWhat(); return err; }
188
189 void withExitStatus(unsigned int status)
190 {
191 err.status = status;
192 }
193
194 void atPos(std::shared_ptr<Pos> pos) {
195 err.pos = pos;
196 }
197
198 void pushTrace(Trace trace)
199 {
200 err.traces.push_front(trace);
201 }
202
203 template<typename... Args>
204 void addTrace(std::shared_ptr<Pos> && e, std::string_view fs, const Args & ... args)
205 {
206 addTrace(std::move(e), HintFmt(std::string(fs), args...));
207 }
208
209 void addTrace(std::shared_ptr<Pos> && e, HintFmt hint);
210
211 bool hasTrace() const { return !err.traces.empty(); }
212
213 const ErrorInfo & info() { return err; };
214};
215
216#define MakeError(newClass, superClass) \
217 /* NOLINTNEXTLINE(bugprone-macro-parentheses) */ \
218 class newClass : public superClass \
219 { \
220 public: \
221 using superClass::superClass; \
222 }
223
224MakeError(Error, BaseError);
225MakeError(UsageError, Error);
226MakeError(UnimplementedError, Error);
227
235class ForeignException : public BaseException
236{
237 std::shared_ptr<std::string> _what;
238
239public:
240 const std::exception_ptr inner;
241 const std::type_info & innerType;
242
243 explicit ForeignException(const std::exception & inner)
244 : _what(std::make_shared<std::string>(inner.what()))
245 , inner(std::make_exception_ptr(inner))
246 , innerType(typeid(inner))
247 {
248 }
249
250 [[noreturn]]
251 void rethrow() const
252 {
253 std::rethrow_exception(inner);
254 }
255
256 template<typename E>
257 E * as() const
258 {
259 try {
260 rethrow();
261 } catch (E & e) { // NOLINT(lix-foreign-exceptions)
262 return &e;
263 } catch (...) {
264 return nullptr;
265 }
266 }
267
268 template<typename E>
269 bool is() const
270 {
271 return as<E>() != nullptr;
272 }
273
274 const char * what() const noexcept override
275 {
276 return _what->c_str();
277 }
278};
279
280class SysError : public Error
281{
282public:
283 int errNo;
284
285 template<typename... Args>
286 SysError(int errNo_, const Args & ... args)
287 : Error("")
288 {
289 errNo = errNo_;
290 auto hf = HintFmt(args...);
291 err.msg = HintFmt("%1%: %2%", Uncolored(hf.str()), strerror(errNo));
292 }
293
294 template<typename... Args>
295 SysError(std::error_code ec, const Args & ... args)
296 : Error("")
297 {
298 errNo = ec.value();
299 auto hf = HintFmt(args...);
300 err.msg = HintFmt("%1%: %2%", Uncolored(hf.str()), ec.message());
301 }
302
303 template<typename... Args>
304 SysError(const Args & ... args)
305 : SysError(errno, args ...)
306 {
307 }
308};
309
320void ignoreExceptionInDestructor(Verbosity lvl = lvlError);
321
329void ignoreExceptionExceptInterrupt(Verbosity lvl = lvlError);
330
331}
Definition args.hh:31
Definition error.hh:140
const std::string & calcWhat() const
Definition error.cc:22
std::optional< std::string > what_
Definition error.hh:147
Definition error.hh:103
Definition fmt.hh:157
Definition suggestions.hh:29
Definition error.hh:80
unsigned int status
Definition error.hh:89
Definition error.hh:57
Definition position.hh:19
Definition error.hh:70
Definition fmt.hh:44
Definition json-fwd.hh:21