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