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