| // Copyright (C) 2017-2019 Baidu, Inc. All Rights Reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // |
| // * Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // * Redistributions in binary form must reproduce the above copyright |
| // notice, this list of conditions and the following disclaimer in |
| // the documentation and/or other materials provided with the |
| // distribution. |
| // * Neither the name of Baidu, Inc., nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| |
| //! Standard library macros |
| //! |
| //! This modules contains a set of macros which are exported from the standard |
| //! library. Each macro is available for use when linking against the standard |
| //! library. |
| |
| /// The entry point for panic of Rust threads. |
| /// |
| /// This macro is used to inject panic into a Rust thread, causing the thread to |
| /// panic entirely. Each thread's panic can be reaped as the `Box<Any>` type, |
| /// and the single-argument form of the `panic!` macro will be the value which |
| /// is transmitted. |
| /// |
| /// The multi-argument form of this macro panics with a string and has the |
| /// `format!` syntax for building a string. |
| /// |
| /// # Current implementation |
| /// |
| /// If the main thread panics it will terminate all your threads and end your |
| /// program with code `101`. |
| /// |
| #[macro_export] |
| #[allow_internal_unstable(__rust_unstable_column, libstd_sys_internals)] |
| macro_rules! panic { |
| () => ({ |
| panic!("explicit panic") |
| }); |
| ($msg:expr) => ({ |
| $crate::rt::begin_panic($msg, &(file!(), line!(), column!())) |
| }); |
| ($msg:expr,) => ({ |
| panic!($msg) |
| }); |
| ($fmt:expr, $($arg:tt)+) => ({ |
| $crate::rt::begin_panic_fmt(&format_args!($fmt, $($arg)+), |
| &(file!(), line!(), column!())) |
| }); |
| } |
| |
| /// Macro for printing to the standard output. |
| /// |
| /// Equivalent to the `println!` macro except that a newline is not printed at |
| /// the end of the message. |
| /// |
| /// Note that stdout is frequently line-buffered by default so it may be |
| /// necessary to use `io::stdout().flush()` to ensure the output is emitted |
| /// immediately. |
| /// |
| /// Use `print!` only for the primary output of your program. Use |
| /// `eprint!` instead to print error and progress messages. |
| /// |
| /// # Panics |
| /// |
| /// Panics if writing to `io::stdout()` fails. |
| #[cfg(feature = "stdio")] |
| #[macro_export] |
| #[allow_internal_unstable(print_internals)] |
| macro_rules! print { |
| ($($arg:tt)*) => ($crate::io::_print(format_args!($($arg)*))); |
| } |
| |
| /// Macro for printing to the standard output, with a newline. On all |
| /// platforms, the newline is the LINE FEED character (`\n`/`U+000A`) alone |
| /// (no additional CARRIAGE RETURN (`\r`/`U+000D`). |
| /// |
| /// Use the `format!` syntax to write data to the standard output. |
| /// See `std::fmt` for more information. |
| /// |
| /// Use `println!` only for the primary output of your program. Use |
| /// `eprintln!` instead to print error and progress messages. |
| /// |
| /// # Panics |
| /// |
| /// Panics if writing to `io::stdout` fails. |
| #[cfg(feature = "stdio")] |
| #[macro_export] |
| macro_rules! println { |
| () => (print!("\n")); |
| ($fmt:expr) => (print!(concat!($fmt, "\n"))); |
| ($fmt:expr, $($arg:tt)*) => (print!(concat!($fmt, "\n"), $($arg)*)); |
| } |
| |
| #[cfg(not(feature = "stdio"))] |
| #[macro_export] |
| macro_rules! print { ($($arg:tt)*) => ({}) } |
| |
| #[cfg(not(feature = "stdio"))] |
| #[macro_export] |
| macro_rules! println { ($($arg:tt)*) => ({}) } |
| |
| /// Macro for printing to the standard error. |
| /// |
| /// Equivalent to the `print!` macro, except that output goes to |
| /// `io::stderr` instead of `io::stdout`. See `print!` for |
| /// example usage. |
| /// |
| /// Use `eprint!` only for error and progress messages. Use `print!` |
| /// instead for the primary output of your program. |
| /// |
| /// # Panics |
| /// |
| /// Panics if writing to `io::stderr` fails. |
| #[cfg(feature = "stdio")] |
| #[macro_export] |
| #[allow_internal_unstable(print_internals, format_args_nl)] |
| macro_rules! eprint { |
| ($($arg:tt)*) => ($crate::io::_eprint(format_args!($($arg)*))); |
| } |
| |
| /// Macro for printing to the standard error, with a newline. |
| /// |
| /// Equivalent to the `println!` macro, except that output goes to |
| /// `io::stderr` instead of `io::stdout`. See `println!` for |
| /// example usage. |
| /// |
| /// Use `eprintln!` only for error and progress messages. Use `println!` |
| /// instead for the primary output of your program. |
| /// |
| /// # Panics |
| /// |
| /// Panics if writing to `io::stderr` fails. |
| #[cfg(feature = "stdio")] |
| #[macro_export] |
| macro_rules! eprintln { |
| () => (eprint!("\n")); |
| ($fmt:expr) => (eprint!(concat!($fmt, "\n"))); |
| ($fmt:expr, $($arg:tt)*) => (eprint!(concat!($fmt, "\n"), $($arg)*)); |
| } |
| |
| #[cfg(not(feature = "stdio"))] |
| #[macro_export] |
| macro_rules! eprint { ($($arg:tt)*) => ({}) } |
| |
| #[cfg(not(feature = "stdio"))] |
| #[macro_export] |
| macro_rules! eprintln { ($($arg:tt)*) => ({}) } |
| |
| /// Prints and returns the value of a given expression for quick and dirty |
| /// debugging. |
| /// |
| /// An example: |
| /// |
| /// ```rust |
| /// let a = 2; |
| /// let b = dbg!(a * 2) + 1; |
| /// // ^-- prints: [src/main.rs:2] a * 2 = 4 |
| /// assert_eq!(b, 5); |
| /// ``` |
| /// |
| /// The macro works by using the `Debug` implementation of the type of |
| /// the given expression to print the value to [stderr] along with the |
| /// source location of the macro invocation as well as the source code |
| /// of the expression. |
| /// |
| /// Invoking the macro on an expression moves and takes ownership of it |
| /// before returning the evaluated expression unchanged. If the type |
| /// of the expression does not implement `Copy` and you don't want |
| /// to give up ownership, you can instead borrow with `dbg!(&expr)` |
| /// for some expression `expr`. |
| /// |
| /// The `dbg!` macro works exactly the same in release builds. |
| /// This is useful when debugging issues that only occur in release |
| /// builds or when debugging in release mode is significantly faster. |
| /// |
| /// Note that the macro is intended as a debugging tool and therefore you |
| /// should avoid having uses of it in version control for longer periods. |
| /// Use cases involving debug output that should be added to version control |
| /// are better served by macros such as [`debug!`] from the [`log`] crate. |
| /// |
| /// # Stability |
| /// |
| /// The exact output printed by this macro should not be relied upon |
| /// and is subject to future changes. |
| /// |
| /// # Panics |
| /// |
| /// Panics if writing to `io::stderr` fails. |
| /// |
| /// # Further examples |
| /// |
| /// With a method call: |
| /// |
| /// ```rust |
| /// fn foo(n: usize) { |
| /// if let Some(_) = dbg!(n.checked_sub(4)) { |
| /// // ... |
| /// } |
| /// } |
| /// |
| /// foo(3) |
| /// ``` |
| /// |
| /// This prints to [stderr]: |
| /// |
| /// ```text,ignore |
| /// [src/main.rs:4] n.checked_sub(4) = None |
| /// ``` |
| /// |
| /// Naive factorial implementation: |
| /// |
| /// ```rust |
| /// fn factorial(n: u32) -> u32 { |
| /// if dbg!(n <= 1) { |
| /// dbg!(1) |
| /// } else { |
| /// dbg!(n * factorial(n - 1)) |
| /// } |
| /// } |
| /// |
| /// dbg!(factorial(4)); |
| /// ``` |
| /// |
| /// This prints to [stderr]: |
| /// |
| /// ```text,ignore |
| /// [src/main.rs:3] n <= 1 = false |
| /// [src/main.rs:3] n <= 1 = false |
| /// [src/main.rs:3] n <= 1 = false |
| /// [src/main.rs:3] n <= 1 = true |
| /// [src/main.rs:4] 1 = 1 |
| /// [src/main.rs:5] n * factorial(n - 1) = 2 |
| /// [src/main.rs:5] n * factorial(n - 1) = 6 |
| /// [src/main.rs:5] n * factorial(n - 1) = 24 |
| /// [src/main.rs:11] factorial(4) = 24 |
| /// ``` |
| /// |
| /// The `dbg!(..)` macro moves the input: |
| /// |
| /// ```compile_fail |
| /// /// A wrapper around `usize` which importantly is not Copyable. |
| /// #[derive(Debug)] |
| /// struct NoCopy(usize); |
| /// |
| /// let a = NoCopy(42); |
| /// let _ = dbg!(a); // <-- `a` is moved here. |
| /// let _ = dbg!(a); // <-- `a` is moved again; error! |
| /// ``` |
| /// |
| /// You can also use `dbg!()` without a value to just print the |
| /// file and line whenever it's reached. |
| /// |
| /// Finally, if you want to `dbg!(..)` multiple values, it will treat them as |
| /// a tuple (and return it, too): |
| /// |
| /// ``` |
| /// assert_eq!(dbg!(1usize, 2u32), (1, 2)); |
| /// ``` |
| /// |
| /// However, a single argument with a trailing comma will still not be treated |
| /// as a tuple, following the convention of ignoring trailing commas in macro |
| /// invocations. You can use a 1-tuple directly if you need one: |
| /// |
| /// ``` |
| /// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored |
| /// assert_eq!((1,), dbg!((1u32,))); // 1-tuple |
| /// ``` |
| /// |
| /// [stderr]: https://en.wikipedia.org/wiki/Standard_streams#Standard_error_(stderr) |
| /// [`debug!`]: https://docs.rs/log/*/log/macro.debug.html |
| /// [`log`]: https://crates.io/crates/log |
| #[macro_export] |
| macro_rules! dbg { |
| () => { |
| $crate::eprintln!("[{}:{}]", file!(), line!()); |
| }; |
| ($val:expr) => { |
| // Use of `match` here is intentional because it affects the lifetimes |
| // of temporaries - https://stackoverflow.com/a/48732525/1063961 |
| match $val { |
| tmp => { |
| $crate::eprintln!("[{}:{}] {} = {:#?}", |
| file!(), line!(), stringify!($val), &tmp); |
| tmp |
| } |
| } |
| }; |
| // Trailing comma with single argument is ignored |
| ($val:expr,) => { $crate::dbg!($val) }; |
| ($($val:expr),+ $(,)?) => { |
| ($($crate::dbg!($val)),+,) |
| }; |
| } |