Line data Source code
1 : #if !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
2 : // @allow-raw-throw
3 : #ifndef C10_UTIL_EXCEPTION_H_
4 : #define C10_UTIL_EXCEPTION_H_
5 :
6 : #include <c10/macros/Export.h>
7 : #include <c10/macros/Macros.h>
8 : #include <c10/util/Backtrace.h>
9 : #include <c10/util/Lazy.h>
10 : #include <c10/util/StringUtil.h>
11 :
12 : #include <cstdint>
13 : #include <exception>
14 : #include <memory>
15 : #include <string>
16 : #include <variant>
17 : #include <vector>
18 :
19 : #if defined(_MSC_VER) && _MSC_VER <= 1900
20 : #define __func__ __FUNCTION__
21 : #endif
22 :
23 : namespace c10 {
24 :
25 : /// The primary ATen error class.
26 : /// Provides a complete error message with source location information via
27 : /// `what()`, and a more concise message via `what_without_backtrace()`.
28 : /// Don't throw this directly; use TORCH_CHECK/TORCH_INTERNAL_ASSERT instead.
29 : ///
30 : /// NB: c10::Error is handled specially by the default torch to suppress the
31 : /// backtrace, see torch/csrc/Exceptions.h
32 : class C10_API Error : public std::exception {
33 : private:
34 : // The actual error message.
35 : std::string msg_;
36 :
37 : // Context for the message (in order of decreasing specificity). Context will
38 : // be automatically formatted appropriately, so it is not necessary to add
39 : // extra leading/trailing newlines to strings inside this vector
40 : std::vector<std::string> context_;
41 :
42 : // The C++ backtrace at the point when this exception was raised. This
43 : // may be empty if there is no valid backtrace. (We don't use optional
44 : // here to reduce the dependencies this file has.)
45 : Backtrace backtrace_;
46 :
47 : // These two are derived fields from msg_stack_ and backtrace_, but we need
48 : // fields for the strings so that we can return a const char* (as the
49 : // signature of std::exception requires). Currently, the invariant
50 : // is that these fields are ALWAYS populated consistently with respect
51 : // to msg_stack_ and backtrace_.
52 : mutable OptimisticLazy<std::string> what_;
53 : std::string what_without_backtrace_;
54 :
55 : // This is a little debugging trick: you can stash a relevant pointer
56 : // in caller, and then when you catch the exception, you can compare
57 : // against pointers you have on hand to get more information about
58 : // where the exception came from. In Caffe2, this is used to figure
59 : // out which operator raised an exception.
60 : const void* caller_;
61 :
62 : public:
63 : // PyTorch-style Error constructor. NB: the implementation of this
64 : // is actually in Logging.cpp
65 : Error(SourceLocation source_location, std::string msg);
66 :
67 : // Caffe2-style error message
68 : Error(
69 : const char* file,
70 : const uint32_t line,
71 : const char* condition,
72 : const std::string& msg,
73 : Backtrace backtrace,
74 : const void* caller = nullptr);
75 :
76 : // Base constructor
77 : Error(
78 : std::string msg,
79 : Backtrace backtrace = nullptr,
80 : const void* caller = nullptr);
81 :
82 : // Add some new context to the message stack. The last added context
83 : // will be formatted at the end of the context list upon printing.
84 : // WARNING: This method is O(n) in the size of the stack, so don't go
85 : // wild adding a ridiculous amount of context to error messages.
86 : void add_context(std::string msg);
87 :
88 : const std::string& msg() const {
89 : return msg_;
90 : }
91 :
92 : const std::vector<std::string>& context() const {
93 : return context_;
94 : }
95 :
96 : const Backtrace& backtrace() const;
97 :
98 : /// Returns the complete error message, including the source location.
99 : /// The returned pointer is invalidated if you call add_context() on
100 : /// this object.
101 : const char* what() const noexcept override;
102 :
103 : const void* caller() const noexcept {
104 : return caller_;
105 : }
106 :
107 : /// Returns only the error message string, without source location.
108 : /// The returned pointer is invalidated if you call add_context() on
109 : /// this object.
110 0 : virtual const char* what_without_backtrace() const noexcept {
111 0 : return what_without_backtrace_.c_str();
112 : }
113 :
114 : private:
115 : void refresh_what();
116 : std::string compute_what(bool include_backtrace) const;
117 : };
118 :
119 : class C10_API Warning {
120 : public:
121 : class C10_API UserWarning{};
122 : class C10_API DeprecationWarning{};
123 :
124 : using warning_variant_t = std::variant<UserWarning, DeprecationWarning>;
125 :
126 : Warning(
127 : warning_variant_t type,
128 : const SourceLocation& source_location,
129 : std::string msg,
130 : bool verbatim);
131 :
132 : Warning(
133 : warning_variant_t type,
134 : SourceLocation source_location,
135 : const char* msg,
136 : bool verbatim);
137 :
138 : Warning(
139 : warning_variant_t type,
140 : SourceLocation source_location,
141 : ::c10::detail::CompileTimeEmptyString msg,
142 : bool verbatim);
143 :
144 : // Getters for members
145 : warning_variant_t type() const;
146 : const SourceLocation& source_location() const;
147 : const std::string& msg() const;
148 : bool verbatim() const;
149 :
150 : private:
151 : // The type of warning
152 : warning_variant_t type_;
153 :
154 : // Where the warning happened.
155 : SourceLocation source_location_;
156 :
157 : // The actual warning message.
158 : std::string msg_;
159 :
160 : // See note: [Verbatim Warnings]
161 : bool verbatim_;
162 : };
163 :
164 : using UserWarning = Warning::UserWarning;
165 : using DeprecationWarning = Warning::DeprecationWarning;
166 :
167 : // Issue a warning with a given message. Dispatched to the current
168 : // warning handler.
169 : void C10_API warn(const Warning& warning);
170 :
171 : class C10_API WarningHandler {
172 : public:
173 : virtual ~WarningHandler() = default;
174 : /// The default warning handler. Prints the message to stderr.
175 : virtual void process(const Warning& warning);
176 : };
177 :
178 : namespace WarningUtils {
179 :
180 : // Note: [Verbatim Warnings]
181 : // Warnings originating in C++ code can appear out-of-place to Python users:
182 : // a user runs a line in Python, but the warning references a line in C++.
183 : // Some parts of PyTorch, like the JIT, are cognizant of this mismatch
184 : // and take care to map warnings back to the user's program, but most
185 : // of PyTorch simply throws a context-free warning. To allow warning
186 : // handlers to add context where appropriate, warn takes the
187 : // "verbatim" flag. When this is false a warning handler might append
188 : // the C++ warning to a Python warning message that relates the warning
189 : // back to the user's program. Callers who have already accounted for
190 : // context in their warnings should set verbatim to true so their warnings
191 : // appear without modification.
192 :
193 : /// Sets the global warning handler. This is not thread-safe, so it should
194 : /// generally be called once during initialization or while holding the GIL
195 : /// for programs that use python.
196 : /// User is responsible for keeping the WarningHandler alive until
197 : /// it is not needed.
198 : C10_API void set_warning_handler(WarningHandler* handler) noexcept(true);
199 : /// Gets the global warning handler.
200 : C10_API WarningHandler* get_warning_handler() noexcept(true);
201 :
202 : class C10_API WarningHandlerGuard {
203 : WarningHandler* prev_handler_;
204 :
205 : public:
206 : WarningHandlerGuard(WarningHandler* new_handler)
207 : : prev_handler_(c10::WarningUtils::get_warning_handler()) {
208 : c10::WarningUtils::set_warning_handler(new_handler);
209 : }
210 : WarningHandlerGuard(WarningHandlerGuard&& other) = delete;
211 : WarningHandlerGuard(const WarningHandlerGuard&) = delete;
212 : WarningHandlerGuard& operator=(const WarningHandlerGuard&) = delete;
213 : WarningHandlerGuard& operator=(WarningHandlerGuard&&) = delete;
214 : ~WarningHandlerGuard() {
215 : c10::WarningUtils::set_warning_handler(prev_handler_);
216 : }
217 : };
218 :
219 : /// The TORCH_WARN_ONCE macro is difficult to test for. Use
220 : /// setWarnAlways(true) to turn it into TORCH_WARN, which can be
221 : /// tested for more easily.
222 : C10_API void set_warnAlways(bool /*setting*/) noexcept(true);
223 : C10_API bool get_warnAlways() noexcept(true);
224 :
225 : // A RAII guard that sets warn_always (not thread-local) on
226 : // construction, and sets it back to the original value upon destruction.
227 : struct C10_API WarnAlways {
228 : public:
229 : explicit WarnAlways(bool setting = true);
230 : ~WarnAlways();
231 :
232 : private:
233 : bool prev_setting;
234 : };
235 :
236 : } // namespace WarningUtils
237 :
238 : // Like Error, but we always report the C++ backtrace, instead of only
239 : // reporting when TORCH_SHOW_CPP_STACKTRACES
240 : class C10_API ErrorAlwaysShowCppStacktrace : public Error {
241 : using Error::Error;
242 : const char* what_without_backtrace() const noexcept override {
243 : return what();
244 : }
245 : };
246 :
247 : // Used in ATen for out-of-bound indices that can reasonably only be detected
248 : // lazily inside a kernel (See: advanced indexing). These turn into
249 : // IndexError when they cross to Python.
250 : class C10_API IndexError : public Error {
251 : using Error::Error;
252 : };
253 :
254 : // Used in ATen for invalid values. These turn into
255 : // ValueError when they cross to Python.
256 : class C10_API ValueError : public Error {
257 0 : using Error::Error;
258 : };
259 :
260 : // Used in ATen for invalid types. These turn into
261 : // TypeError when they cross to Python.
262 : class C10_API TypeError : public Error {
263 : using Error::Error;
264 : };
265 :
266 : // Used in ATen for functionality that is not implemented. These turn into
267 : // NotImplementedError when they cross to Python.
268 : class C10_API NotImplementedError : public Error {
269 0 : using Error::Error;
270 : };
271 :
272 : // Used in ATen for buffer-related errors, e.g. trying to create a DLPack of
273 : // an unsupported device. These turn into BufferError when they cross to
274 : // Python.
275 : class C10_API BufferError : public Error {
276 : using Error::Error;
277 : };
278 :
279 : // Used in ATen for non finite indices. These turn into
280 : // ExitException when they cross to Python.
281 : class C10_API EnforceFiniteError : public Error {
282 : using Error::Error;
283 : };
284 :
285 : // Used in Onnxifi backend lowering. These turn into
286 : // ExitException when they cross to Python.
287 : class C10_API OnnxfiBackendSystemError : public Error {
288 : using Error::Error;
289 : };
290 :
291 : // Used for numerical errors from the linalg module. These
292 : // turn into LinAlgError when they cross into Python.
293 : class C10_API LinAlgError : public Error {
294 : using Error::Error;
295 : };
296 :
297 : class C10_API OutOfMemoryError : public Error {
298 : using Error::Error;
299 : };
300 :
301 : // Used for handling syntactic errors in input arguments.
302 : // These turn into SyntaxError when the cross into Python.
303 : class C10_API SyntaxError : public Error {
304 : using Error::Error;
305 : };
306 :
307 : // Raised when accelerator API call hits an error.
308 : // These turn into AcceleratorError when the cross into Python
309 : class C10_API AcceleratorError : public Error {
310 : int32_t error_code;
311 :
312 : public:
313 : AcceleratorError(SourceLocation loc, int32_t code, const std::string& msg)
314 : : Error(loc, msg), error_code(code) {}
315 : int32_t get_error_code() const {
316 : return error_code;
317 : }
318 : };
319 :
320 : // Base error type for all distributed errors.
321 : // These turn into DistError when they cross into Python.
322 : class C10_API DistError : public Error {
323 : using Error::Error;
324 : };
325 :
326 : // Used for collective communication library errors from the distributed module.
327 : // These turn into DistBackendError when they cross into Python.
328 : class C10_API DistBackendError : public DistError {
329 : using DistError::DistError;
330 : };
331 :
332 : // Used for errors originating from the store.
333 : // These turn into DistStoreError when they cross into Python.
334 : class C10_API DistStoreError : public DistError {
335 : using DistError::DistError;
336 : };
337 :
338 : // Used for errors originating from the TCP/IP stack and not from collective
339 : // libraries. These turn into DistNetworkError when they cross into Python.
340 : class C10_API DistNetworkError : public DistError {
341 : using DistError::DistError;
342 : };
343 :
344 : // Raised when a queue is empty and a non-blocking pop is called.
345 : // Translated to torch.distributed.QueueEmptyError in Python
346 : class C10_API DistQueueEmptyError : public DistStoreError {
347 : using DistStoreError::DistStoreError;
348 : };
349 :
350 : // A utility function to return an exception std::string by prepending its
351 : // exception type before its what() content
352 : C10_API std::string GetExceptionString(const std::exception& e);
353 :
354 : } // namespace c10
355 :
356 : // Private helper macro for implementing TORCH_INTERNAL_ASSERT and TORCH_CHECK
357 : //
358 : // Note: In the debug build With MSVC, __LINE__ might be of long type (a.k.a
359 : // int32_t), which is different from the definition of `SourceLocation` that
360 : // requires unsigned int (a.k.a uint32_t) and may cause a compile error with the
361 : // message: error C2397: conversion from 'long' to 'uint32_t' requires a
362 : // narrowing conversion Here the static cast is used to pass the build. if this
363 : // is used inside a lambda the __func__ macro expands to operator(), which isn't
364 : // very useful, but hard to fix in a macro so suppressing the warning.
365 : #define C10_THROW_ERROR(err_type, msg) \
366 : throw ::c10::err_type( \
367 : {__func__, __FILE__, static_cast<uint32_t>(__LINE__)}, msg)
368 :
369 : #define C10_BUILD_ERROR(err_type, msg) \
370 : ::c10::err_type({__func__, __FILE__, static_cast<uint32_t>(__LINE__)}, msg)
371 :
372 : // Private helper macro for workaround MSVC misexpansion of nested macro
373 : // invocations involving __VA_ARGS__. See
374 : // https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly
375 : #define C10_EXPAND_MSVC_WORKAROUND(x) x
376 :
377 : #include <torch/headeronly/util/Exception.h>
378 :
379 : // ----------------------------------------------------------------------------
380 : // Error reporting macros
381 : // ----------------------------------------------------------------------------
382 :
383 : #ifdef STRIP_ERROR_MESSAGES
384 : #define TORCH_RETHROW(e, ...) \
385 : do { \
386 : (void)e; /* Suppress unused variable warning */ \
387 : throw; \
388 : } while (false)
389 : #else
390 : #define TORCH_RETHROW(e, ...) \
391 : do { \
392 : e.add_context(::c10::str(__VA_ARGS__)); \
393 : throw; \
394 : } while (false)
395 : #endif
396 :
397 : // A utility macro to provide assert()-like functionality; that is, enforcement
398 : // of internal invariants in code. It supports an arbitrary number of extra
399 : // arguments (evaluated only on failure), which will be printed in the assert
400 : // failure message using operator<< (this is useful to print some variables
401 : // which may be useful for debugging.)
402 : //
403 : // Usage:
404 : // TORCH_INTERNAL_ASSERT(should_be_true);
405 : // TORCH_INTERNAL_ASSERT(x == 0, "x = ", x);
406 : //
407 : // Assuming no bugs in PyTorch, the conditions tested by this macro should
408 : // always be true; e.g., it should be possible to disable all of these
409 : // conditions without changing observable user behavior. If you would like to
410 : // do error reporting for user input, please use TORCH_CHECK instead.
411 : //
412 : // NOTE: It is SAFE to use this macro in production code; on failure, this
413 : // simply raises an exception, it does NOT unceremoniously quit the process
414 : // (unlike assert()).
415 : //
416 : #ifdef STRIP_ERROR_MESSAGES
417 : #define TORCH_INTERNAL_ASSERT(cond, ...) \
418 : if (C10_UNLIKELY_OR_CONST(!(cond))) { \
419 : ::c10::detail::torchCheckFail( \
420 : __func__, \
421 : __FILE__, \
422 : static_cast<uint32_t>(__LINE__), \
423 : #cond " INTERNAL ASSERT FAILED at " C10_STRINGIZE(__FILE__)); \
424 : }
425 : #else
426 : // It would be nice if we could build a combined string literal out of
427 : // the TORCH_INTERNAL_ASSERT prefix and a user-provided string literal
428 : // as the first argument, but there doesn't seem to be any good way to
429 : // do that while still supporting having a first argument that isn't a
430 : // string literal.
431 : #define TORCH_INTERNAL_ASSERT(cond, ...) \
432 : if (C10_UNLIKELY_OR_CONST(!(cond))) { \
433 : ::c10::detail::torchInternalAssertFail( \
434 : __func__, \
435 : __FILE__, \
436 : static_cast<uint32_t>(__LINE__), \
437 : #cond \
438 : " INTERNAL ASSERT FAILED at " C10_STRINGIZE(__FILE__) ":" C10_STRINGIZE( \
439 : __LINE__) ", please report a bug to PyTorch. ", \
440 : c10::str(__VA_ARGS__)); \
441 : }
442 : #endif
443 :
444 : // A utility macro to make it easier to test for error conditions from user
445 : // input. Like TORCH_INTERNAL_ASSERT, it supports an arbitrary number of extra
446 : // arguments (evaluated only on failure), which will be printed in the error
447 : // message using operator<< (e.g., you can pass any object which has
448 : // operator<< defined. Most objects in PyTorch have these definitions!)
449 : //
450 : // Usage:
451 : // TORCH_CHECK(should_be_true); // A default error message will be provided
452 : // // in this case; but we recommend writing an
453 : // // explicit error message, as it is more
454 : // // user friendly.
455 : // TORCH_CHECK(x == 0, "Expected x to be 0, but got ", x);
456 : //
457 : // On failure, this macro will raise an exception. If this exception propagates
458 : // to Python, it will convert into a Python RuntimeError.
459 : //
460 : // NOTE: It is SAFE to use this macro in production code; on failure, this
461 : // simply raises an exception, it does NOT unceremoniously quit the process
462 : // (unlike CHECK() from glog.)
463 : //
464 : #define TORCH_CHECK_WITH(error_t, cond, ...) \
465 : TORCH_CHECK_WITH_MSG(error_t, cond, "", __VA_ARGS__)
466 :
467 : #ifdef STRIP_ERROR_MESSAGES
468 : #define TORCH_CHECK_MSG(cond, type, ...) \
469 : (#cond #type " CHECK FAILED at " C10_STRINGIZE(__FILE__))
470 : #define TORCH_CHECK_WITH_MSG(error_t, cond, type, ...) \
471 : if (C10_UNLIKELY_OR_CONST(!(cond))) { \
472 : C10_THROW_ERROR(Error, TORCH_CHECK_MSG(cond, type, __VA_ARGS__)); \
473 : }
474 : #else
475 :
476 : namespace c10::detail {
477 : template <typename... Args>
478 0 : auto torchCheckMsgImpl(const char* /*msg*/, const Args&... args) {
479 0 : return ::c10::str(args...);
480 : }
481 : inline C10_API const char* torchCheckMsgImpl(const char* msg) {
482 : return msg;
483 : }
484 : // If there is just 1 user-provided C-string argument, use it.
485 : inline C10_API const char* torchCheckMsgImpl(
486 : const char* /*msg*/,
487 : const char* args) {
488 : return args;
489 : }
490 : } // namespace c10::detail
491 :
492 : #define TORCH_CHECK_MSG(cond, type, ...) \
493 : (::c10::detail::torchCheckMsgImpl( \
494 : "Expected " #cond \
495 : " to be true, but got false. " \
496 : "(Could this error message be improved? If so, " \
497 : "please report an enhancement request to PyTorch.)", \
498 : ##__VA_ARGS__))
499 : #define TORCH_CHECK_WITH_MSG(error_t, cond, type, ...) \
500 : if (C10_UNLIKELY_OR_CONST(!(cond))) { \
501 : C10_THROW_ERROR(error_t, TORCH_CHECK_MSG(cond, type, __VA_ARGS__)); \
502 : }
503 : #endif
504 :
505 : namespace c10::detail {
506 :
507 : [[noreturn]] C10_API void torchCheckFail(
508 : const char* func,
509 : const char* file,
510 : uint32_t line,
511 : const std::string& msg);
512 : [[noreturn]] C10_API void torchCheckFail(
513 : const char* func,
514 : const char* file,
515 : uint32_t line,
516 : const char* msg);
517 :
518 : // The c10::str() call that creates userMsg can have 1 of 3 return
519 : // types depending on the number and types of arguments passed to
520 : // TORCH_INTERNAL_ASSERT. 0 arguments will get a
521 : // CompileTimeEmptyString, 1 const char * will be passed straight
522 : // through, and anything else will get converted to std::string.
523 : [[noreturn]] C10_API void torchInternalAssertFail(
524 : const char* func,
525 : const char* file,
526 : uint32_t line,
527 : const char* condMsg,
528 : const char* userMsg);
529 : [[noreturn]] inline C10_API void torchInternalAssertFail(
530 : const char* func,
531 : const char* file,
532 : uint32_t line,
533 : const char* condMsg,
534 : ::c10::detail::CompileTimeEmptyString /*userMsg*/) {
535 0 : torchCheckFail(func, file, line, condMsg);
536 : }
537 : [[noreturn]] C10_API void torchInternalAssertFail(
538 : const char* func,
539 : const char* file,
540 : uint32_t line,
541 : const char* condMsg,
542 : const std::string& userMsg);
543 :
544 : } // namespace c10::detail
545 :
546 : #ifdef STANDALONE_TORCH_HEADER
547 :
548 : // TORCH_CHECK throws std::runtime_error instead of c10::Error which is
549 : // useful when certain headers are used in a libtorch-independent way,
550 : // e.g. when Vectorized<T> is used in AOTInductor generated code.
551 : #ifdef STRIP_ERROR_MESSAGES
552 : #define TORCH_CHECK(cond, ...) \
553 : if (C10_UNLIKELY_OR_CONST(!(cond))) { \
554 : throw std::runtime_error(TORCH_CHECK_MSG( \
555 : cond, \
556 : "", \
557 : __func__, \
558 : ", ", \
559 : __FILE__, \
560 : ":", \
561 : __LINE__, \
562 : ", ", \
563 : __VA_ARGS__)); \
564 : }
565 : #else
566 : #define TORCH_CHECK(cond, ...) \
567 : if (C10_UNLIKELY_OR_CONST(!(cond))) { \
568 : throw std::runtime_error(TORCH_CHECK_MSG( \
569 : cond, \
570 : "", \
571 : __func__, \
572 : ", ", \
573 : __FILE__, \
574 : ":", \
575 : __LINE__, \
576 : ", ", \
577 : ##__VA_ARGS__)); \
578 : }
579 : #endif
580 :
581 : #else
582 :
583 : #ifdef STRIP_ERROR_MESSAGES
584 : #define TORCH_CHECK(cond, ...) \
585 : if (C10_UNLIKELY_OR_CONST(!(cond))) { \
586 : ::c10::detail::torchCheckFail( \
587 : __func__, \
588 : __FILE__, \
589 : static_cast<uint32_t>(__LINE__), \
590 : TORCH_CHECK_MSG(cond, "", __VA_ARGS__)); \
591 : }
592 : #else
593 : #define TORCH_CHECK(cond, ...) \
594 : if (C10_UNLIKELY_OR_CONST(!(cond))) { \
595 : ::c10::detail::torchCheckFail( \
596 : __func__, \
597 : __FILE__, \
598 : static_cast<uint32_t>(__LINE__), \
599 : TORCH_CHECK_MSG(cond, "", ##__VA_ARGS__)); \
600 : }
601 : #endif
602 :
603 : #endif
604 :
605 : // An utility macro that does what `TORCH_CHECK` does if compiled in the host
606 : // code, otherwise does nothing. Supposed to be used in the code shared between
607 : // host and device code as an alternative for `TORCH_CHECK`.
608 : #if defined(__CUDACC__) || defined(__HIPCC__)
609 : #define TORCH_CHECK_IF_NOT_ON_CUDA(cond, ...)
610 : #else
611 : #define TORCH_CHECK_IF_NOT_ON_CUDA(cond, ...) TORCH_CHECK(cond, ##__VA_ARGS__)
612 : #endif
613 :
614 : // Debug only version of TORCH_INTERNAL_ASSERT. This macro only checks in debug
615 : // build, and does nothing in release build. It is appropriate to use
616 : // in situations where you want to add an assert to a hotpath, but it is
617 : // too expensive to run this assert on production builds.
618 : #ifdef NDEBUG
619 : // Optimized version - generates no code.
620 : #define TORCH_INTERNAL_ASSERT_DEBUG_ONLY(...) \
621 : while (false) \
622 : C10_EXPAND_MSVC_WORKAROUND(TORCH_INTERNAL_ASSERT(__VA_ARGS__))
623 : #else
624 : #define TORCH_INTERNAL_ASSERT_DEBUG_ONLY(...) \
625 : C10_EXPAND_MSVC_WORKAROUND(TORCH_INTERNAL_ASSERT(__VA_ARGS__))
626 : #endif
627 :
628 : // TODO: We're going to get a lot of similar looking string literals
629 : // this way; check if this actually affects binary size.
630 :
631 : // Like TORCH_CHECK, but raises LinAlgError instead of Error.
632 : #define TORCH_CHECK_LINALG(cond, ...) \
633 : TORCH_CHECK_WITH_MSG(LinAlgError, cond, "LINALG", __VA_ARGS__)
634 :
635 : // Like TORCH_CHECK, but raises IndexErrors instead of Errors.
636 : #define TORCH_CHECK_INDEX(cond, ...) \
637 : TORCH_CHECK_WITH_MSG(IndexError, cond, "INDEX", __VA_ARGS__)
638 :
639 : // Like TORCH_CHECK, but raises ValueErrors instead of Errors.
640 : #define TORCH_CHECK_VALUE(cond, ...) \
641 : TORCH_CHECK_WITH_MSG(ValueError, cond, "VALUE", __VA_ARGS__)
642 :
643 : // Like TORCH_CHECK, but raises TypeErrors instead of Errors.
644 : #define TORCH_CHECK_TYPE(cond, ...) \
645 : TORCH_CHECK_WITH_MSG(TypeError, cond, "TYPE", __VA_ARGS__)
646 :
647 : // Like TORCH_CHECK, but raises NotImplementedErrors instead of Errors.
648 : #define TORCH_CHECK_NOT_IMPLEMENTED(cond, ...) \
649 : TORCH_CHECK_WITH_MSG(NotImplementedError, cond, "TYPE", __VA_ARGS__)
650 :
651 : // Like TORCH_CHECK, but raises BufferError instead of Errors.
652 : #define TORCH_CHECK_BUFFER(cond, ...) \
653 : TORCH_CHECK_WITH_MSG(BufferError, cond, "TYPE", __VA_ARGS__)
654 :
655 : #define TORCH_CHECK_ALWAYS_SHOW_CPP_STACKTRACE(cond, ...) \
656 : TORCH_CHECK_WITH_MSG( \
657 : ErrorAlwaysShowCppStacktrace, cond, "TYPE", ##__VA_ARGS__)
658 :
659 : #ifdef STRIP_ERROR_MESSAGES
660 : #define WARNING_MESSAGE_STRING(...) \
661 : ::c10::detail::CompileTimeEmptyString {}
662 : #else
663 : #define WARNING_MESSAGE_STRING(...) ::c10::str(__VA_ARGS__)
664 : #endif
665 :
666 : // Report a warning to the user. Accepts an arbitrary number of extra
667 : // arguments which are concatenated into the warning message using operator<<
668 : //
669 : #ifdef DISABLE_WARN
670 : #define _TORCH_WARN_WITH(...) ((void)0);
671 : #else
672 : #define _TORCH_WARN_WITH(warning_t, ...) \
673 : ::c10::warn(::c10::Warning( \
674 : warning_t(), \
675 : {__func__, __FILE__, static_cast<uint32_t>(__LINE__)}, \
676 : WARNING_MESSAGE_STRING(__VA_ARGS__), \
677 : false));
678 : #endif
679 :
680 : #define TORCH_WARN(...) _TORCH_WARN_WITH(::c10::UserWarning, __VA_ARGS__);
681 :
682 : #define TORCH_WARN_DEPRECATION(...) \
683 : _TORCH_WARN_WITH(::c10::DeprecationWarning, __VA_ARGS__);
684 :
685 : // Report a warning to the user only once. Accepts an arbitrary number of extra
686 : // arguments which are concatenated into the warning message using operator<<
687 : //
688 : #define _TORCH_WARN_ONCE(...) \
689 : [[maybe_unused]] static const auto C10_ANONYMOUS_VARIABLE( \
690 : torch_warn_once_) = [&] { \
691 : TORCH_WARN(__VA_ARGS__); \
692 : return true; \
693 : }()
694 :
695 : #ifdef DISABLE_WARN
696 : #define TORCH_WARN_ONCE(...) ((void)0);
697 : #else
698 : #define TORCH_WARN_ONCE(...) \
699 : if (::c10::WarningUtils::get_warnAlways()) { \
700 : TORCH_WARN(__VA_ARGS__); \
701 : } else { \
702 : _TORCH_WARN_ONCE(__VA_ARGS__); \
703 : }
704 : #endif
705 :
706 : // Report an error with a specific argument
707 : // NOTE: using the argument name in TORCH_CHECK's message is preferred
708 : #define TORCH_CHECK_ARG(cond, argN, ...) \
709 : TORCH_CHECK(cond, "invalid argument ", argN, ": ", __VA_ARGS__)
710 :
711 : #ifndef FATAL_IF
712 : #ifdef C10_USE_GLOG
713 : #define FATAL_IF(condition) \
714 : condition ? (void)0 \
715 : : ::c10::LoggerVoidify() & \
716 : ::c10::MessageLogger( \
717 : ::c10::SourceLocation::current(), ::google::GLOG_FATAL) \
718 : .stream()
719 : #else
720 : #define FATAL_IF(condition) \
721 : condition ? (void)0 \
722 : : ::c10::LoggerVoidify() & \
723 : ::c10::MessageLogger( \
724 : ::c10::SourceLocation::current(), ::c10::GLOG_FATAL) \
725 : .stream()
726 : #endif
727 : #endif
728 :
729 : #ifndef NON_FATAL_IF
730 : #ifdef C10_USE_GLOG
731 : #define NON_FATAL_IF(condition) \
732 : condition ? (void)0 \
733 : : ::c10::LoggerVoidify() & \
734 : ::c10::MessageLogger( \
735 : ::c10::SourceLocation::current(), ::google::GLOG_FATAL, false) \
736 : .stream()
737 : #else
738 : #define NON_FATAL_IF(condition) \
739 : condition ? (void)0 \
740 : : ::c10::LoggerVoidify() & \
741 : ::c10::MessageLogger( \
742 : ::c10::SourceLocation::current(), ::c10::GLOG_FATAL, false) \
743 : .stream()
744 : #endif
745 : #endif
746 :
747 : // Binary comparison check macros
748 : #define TORCH_CHECK_OP(val1, val2, op) \
749 : NON_FATAL_IF(((val1)op(val2))) \
750 : << "Check failed: " #val1 " " #op " " #val2 " (" << (val1) << " vs. " \
751 : << (val2) << "). "
752 :
753 : #define TORCH_DCHECK_OP(val1, val2, op) \
754 : FATAL_IF(((val1)op(val2))) << "Check failed: " #val1 " " #op " " #val2 " (" \
755 : << (val1) << " vs. " << (val2) << "). "
756 :
757 : #define TORCH_CHECK_EQ(val1, val2) TORCH_CHECK_OP(val1, val2, ==)
758 : #define TORCH_CHECK_NE(val1, val2) TORCH_CHECK_OP(val1, val2, !=)
759 : #define TORCH_CHECK_LE(val1, val2) TORCH_CHECK_OP(val1, val2, <=)
760 : #define TORCH_CHECK_LT(val1, val2) TORCH_CHECK_OP(val1, val2, <)
761 : #define TORCH_CHECK_GE(val1, val2) TORCH_CHECK_OP(val1, val2, >=)
762 : #define TORCH_CHECK_GT(val1, val2) TORCH_CHECK_OP(val1, val2, >)
763 :
764 : // Debug versions of TORCH_CHECK_OP macros
765 : #ifndef NDEBUG
766 : #define TORCH_DCHECK_EQ(val1, val2) TORCH_DCHECK_OP(val1, val2, ==)
767 : #define TORCH_DCHECK_NE(val1, val2) TORCH_DCHECK_OP(val1, val2, !=)
768 : #define TORCH_DCHECK_LE(val1, val2) TORCH_DCHECK_OP(val1, val2, <=)
769 : #define TORCH_DCHECK_LT(val1, val2) TORCH_DCHECK_OP(val1, val2, <)
770 : #define TORCH_DCHECK_GE(val1, val2) TORCH_DCHECK_OP(val1, val2, >=)
771 : #define TORCH_DCHECK_GT(val1, val2) TORCH_DCHECK_OP(val1, val2, >)
772 : #else // !NDEBUG
773 : // Optimized versions - generate no code
774 : #define TORCH_DCHECK_EQ(val1, val2) \
775 : while (false) \
776 : TORCH_DCHECK_OP(val1, val2, ==)
777 : #define TORCH_DCHECK_NE(val1, val2) \
778 : while (false) \
779 : TORCH_DCHECK_OP(val1, val2, !=)
780 : #define TORCH_DCHECK_LE(val1, val2) \
781 : while (false) \
782 : TORCH_DCHECK_OP(val1, val2, <=)
783 : #define TORCH_DCHECK_LT(val1, val2) \
784 : while (false) \
785 : TORCH_DCHECK_OP(val1, val2, <)
786 : #define TORCH_DCHECK_GE(val1, val2) \
787 : while (false) \
788 : TORCH_DCHECK_OP(val1, val2, >=)
789 : #define TORCH_DCHECK_GT(val1, val2) \
790 : while (false) \
791 : TORCH_DCHECK_OP(val1, val2, >)
792 : #endif // NDEBUG
793 :
794 : // Null pointer check macro
795 : #define TORCH_CHECK_NOTNULL(val) \
796 : ::c10::CheckNotNull(__FILE__, __LINE__, #val, (val), false)
797 :
798 : #ifndef NDEBUG
799 : #define TORCH_DCHECK_NOTNULL(val) \
800 : ::c10::CheckNotNull(__FILE__, __LINE__, #val, (val), true)
801 : #else // !NDEBUG
802 : #define TORCH_DCHECK_NOTNULL(val) \
803 : while (false) \
804 : TORCH_CHECK_NOTNULL(val)
805 : #endif // NDEBUG
806 :
807 : // ----------------------------------------------------------------------------
808 : // Deprecated macros
809 : // ----------------------------------------------------------------------------
810 :
811 : namespace c10::detail {
812 :
813 : /*
814 : // Deprecation disabled until we fix sites in our codebase
815 : [[deprecated("AT_ERROR(msg) is deprecated, use TORCH_CHECK(false, msg)
816 : instead.")]]
817 : */
818 : inline void deprecated_AT_ERROR() {}
819 :
820 : /*
821 : // Deprecation disabled until we fix sites in our codebase
822 : [[deprecated("AT_ASSERT is deprecated, if you mean to indicate an
823 : internal invariant failure, use " \
824 : "TORCH_INTERNAL_ASSERT instead; if you mean to do user
825 : error checking, use " \ "TORCH_CHECK. See
826 : https://github.com/pytorch/pytorch/issues/20287 for more details.")]]
827 : */
828 : inline void deprecated_AT_ASSERT() {}
829 :
830 : /*
831 : // Deprecation disabled until we fix sites in our codebase
832 : [[deprecated("AT_ASSERTM is deprecated, if you mean to indicate an
833 : internal invariant failure, use " \
834 : "TORCH_INTERNAL_ASSERT instead; if you mean to do user
835 : error checking, use " \ "TORCH_CHECK. See
836 : https://github.com/pytorch/pytorch/issues/20287 for more details.")]]
837 : */
838 : inline void deprecated_AT_ASSERTM() {}
839 :
840 : } // namespace c10::detail
841 :
842 : // Deprecated alias; this alias was deprecated because people kept mistakenly
843 : // using it for user error checking. Use TORCH_INTERNAL_ASSERT or TORCH_CHECK
844 : // instead. See https://github.com/pytorch/pytorch/issues/20287 for more
845 : // details.
846 : #define AT_ASSERT(...) \
847 : do { \
848 : ::c10::detail::deprecated_AT_ASSERT(); \
849 : C10_EXPAND_MSVC_WORKAROUND(TORCH_INTERNAL_ASSERT(__VA_ARGS__)); \
850 : } while (false)
851 :
852 : // Deprecated alias, like AT_ASSERT. The new TORCH_INTERNAL_ASSERT macro
853 : // supports both 0-ary and variadic calls, so having a separate
854 : // message-accepting macro is not necessary.
855 : //
856 : // NB: we MUST include cond explicitly here, as MSVC will miscompile the macro
857 : // expansion, shunting all of __VA_ARGS__ to cond. An alternate workaround
858 : // can be seen at
859 : // https://stackoverflow.com/questions/5134523/msvc-doesnt-expand-va-args-correctly
860 : #define AT_ASSERTM(cond, ...) \
861 : do { \
862 : ::c10::detail::deprecated_AT_ASSERTM(); \
863 : C10_EXPAND_MSVC_WORKAROUND(TORCH_INTERNAL_ASSERT(cond, __VA_ARGS__)); \
864 : } while (false)
865 :
866 : // Deprecated alias; this alias was deprecated because it represents extra API
867 : // surface that makes it hard for people to understand what macro to use.
868 : // Use TORCH_CHECK(false, ...) or TORCH_INTERNAL_ASSERT(false, ...) to
869 : // unconditionally fail at a line of code.
870 : #define AT_ERROR(...) \
871 : do { \
872 : ::c10::detail::deprecated_AT_ERROR(); \
873 : C10_EXPAND_MSVC_WORKAROUND(TORCH_CHECK(false, ::c10::str(__VA_ARGS__))); \
874 : } while (false)
875 :
876 : #endif // C10_UTIL_EXCEPTION_H_
877 :
878 : #else
879 : #error "This file should not be included when either TORCH_STABLE_ONLY or TORCH_TARGET_VERSION is defined."
880 : #endif // !defined(TORCH_STABLE_ONLY) && !defined(TORCH_TARGET_VERSION)
|