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