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