368 lines
11 KiB
Rust
368 lines
11 KiB
Rust
//! 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.
|
|
|
|
/// Panics the current thread.
|
|
///
|
|
/// This allows a program to terminate immediately and provide feedback
|
|
/// to the caller of the program. `panic!` should be used when a program reaches
|
|
/// an unrecoverable state.
|
|
///
|
|
/// This macro is the perfect way to assert conditions in example code and in
|
|
/// tests. `panic!` is closely tied with the `unwrap` method of both [`Option`]
|
|
/// and [`Result`][runwrap] enums. Both implementations call `panic!` when they are set
|
|
/// to None or Err variants.
|
|
///
|
|
/// 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.
|
|
///
|
|
/// [`Result`] enum is often a better solution for recovering from errors than
|
|
/// using the `panic!` macro. This macro should be used to avoid proceeding using
|
|
/// incorrect values, such as from external sources. Detailed information about
|
|
/// error handling is found in the [book].
|
|
///
|
|
/// The multi-argument form of this macro panics with a string and has the
|
|
/// [`format!`] syntax for building a string.
|
|
///
|
|
/// See also the macro [`compile_error!`], for raising errors during compilation.
|
|
///
|
|
/// [runwrap]: ../std/result/enum.Result.html#method.unwrap
|
|
/// [`Option`]: ../std/option/enum.Option.html#method.unwrap
|
|
/// [`Result`]: ../std/result/enum.Result.html
|
|
/// [`format!`]: ../std/macro.format.html
|
|
/// [`compile_error!`]: ../std/macro.compile_error.html
|
|
/// [book]: ../book/ch09-00-error-handling.html
|
|
///
|
|
/// # Current implementation
|
|
///
|
|
/// If the main thread panics it will terminate all your threads and end your
|
|
/// program with code `101`.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```should_panic
|
|
/// # #![allow(unreachable_code)]
|
|
/// panic!();
|
|
/// panic!("this is a terrible mistake!");
|
|
/// panic!(4); // panic with the value of 4 to be collected elsewhere
|
|
/// panic!("this is a {} {message}", "fancy", message = "message");
|
|
/// ```
|
|
#[macro_export]
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[allow_internal_unstable(libstd_sys_internals)]
|
|
macro_rules! panic {
|
|
() => ({
|
|
$crate::panic!("explicit panic")
|
|
});
|
|
($msg:expr) => ({
|
|
$crate::rt::begin_panic($msg, &($crate::file!(), $crate::line!(), $crate::column!()))
|
|
});
|
|
($msg:expr,) => ({
|
|
$crate::panic!($msg)
|
|
});
|
|
($fmt:expr, $($arg:tt)+) => ({
|
|
$crate::rt::begin_panic_fmt(&$crate::format_args!($fmt, $($arg)+),
|
|
&($crate::file!(), $crate::line!(), $crate::column!()))
|
|
});
|
|
}
|
|
|
|
/// Prints 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()`][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.
|
|
///
|
|
/// [`println!`]: ../std/macro.println.html
|
|
/// [flush]: ../std/io/trait.Write.html#tymethod.flush
|
|
/// [`eprint!`]: ../std/macro.eprint.html
|
|
///
|
|
/// # Panics
|
|
///
|
|
/// Panics if writing to `io::stdout()` fails.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// use std::io::{self, Write};
|
|
///
|
|
/// print!("this ");
|
|
/// print!("will ");
|
|
/// print!("be ");
|
|
/// print!("on ");
|
|
/// print!("the ");
|
|
/// print!("same ");
|
|
/// print!("line ");
|
|
///
|
|
/// io::stdout().flush().unwrap();
|
|
///
|
|
/// print!("this string has a newline, why not choose println! instead?\n");
|
|
///
|
|
/// io::stdout().flush().unwrap();
|
|
/// ```
|
|
#[macro_export]
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[allow_internal_unstable(print_internals)]
|
|
macro_rules! print {
|
|
($($arg:tt)*) => ($crate::io::_print($crate::format_args!($($arg)*)));
|
|
}
|
|
|
|
/// Prints 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.
|
|
///
|
|
/// [`format!`]: ../std/macro.format.html
|
|
/// [`std::fmt`]: ../std/fmt/index.html
|
|
/// [`eprintln!`]: ../std/macro.eprintln.html
|
|
/// # Panics
|
|
///
|
|
/// Panics if writing to `io::stdout` fails.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// println!(); // prints just a newline
|
|
/// println!("hello there!");
|
|
/// println!("format {} arguments", "some");
|
|
/// ```
|
|
#[macro_export]
|
|
#[stable(feature = "rust1", since = "1.0.0")]
|
|
#[allow_internal_unstable(print_internals, format_args_nl)]
|
|
macro_rules! println {
|
|
() => ($crate::print!("\n"));
|
|
($($arg:tt)*) => ({
|
|
$crate::io::_print($crate::format_args_nl!($($arg)*));
|
|
})
|
|
}
|
|
|
|
/// Prints 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.
|
|
///
|
|
/// [`io::stderr`]: ../std/io/struct.Stderr.html
|
|
/// [`print!`]: ../std/macro.print.html
|
|
///
|
|
/// # Panics
|
|
///
|
|
/// Panics if writing to `io::stderr` fails.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// eprint!("Error: Could not complete task");
|
|
/// ```
|
|
#[macro_export]
|
|
#[stable(feature = "eprint", since = "1.19.0")]
|
|
#[allow_internal_unstable(print_internals)]
|
|
macro_rules! eprint {
|
|
($($arg:tt)*) => ($crate::io::_eprint($crate::format_args!($($arg)*)));
|
|
}
|
|
|
|
/// Prints 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.
|
|
///
|
|
/// [`io::stderr`]: ../std/io/struct.Stderr.html
|
|
/// [`println!`]: ../std/macro.println.html
|
|
///
|
|
/// # Panics
|
|
///
|
|
/// Panics if writing to `io::stderr` fails.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```
|
|
/// eprintln!("Error: Could not complete task");
|
|
/// ```
|
|
#[macro_export]
|
|
#[stable(feature = "eprint", since = "1.19.0")]
|
|
#[allow_internal_unstable(print_internals, format_args_nl)]
|
|
macro_rules! eprintln {
|
|
() => ($crate::eprint!("\n"));
|
|
($($arg:tt)*) => ({
|
|
$crate::io::_eprint($crate::format_args_nl!($($arg)*));
|
|
})
|
|
}
|
|
|
|
/// 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]
|
|
#[stable(feature = "dbg_macro", since = "1.32.0")]
|
|
macro_rules! dbg {
|
|
() => {
|
|
$crate::eprintln!("[{}:{}]", $crate::file!(), $crate::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!("[{}:{}] {} = {:#?}",
|
|
$crate::file!(), $crate::line!(), $crate::stringify!($val), &tmp);
|
|
tmp
|
|
}
|
|
}
|
|
};
|
|
// Trailing comma with single argument is ignored
|
|
($val:expr,) => { $crate::dbg!($val) };
|
|
($($val:expr),+ $(,)?) => {
|
|
($($crate::dbg!($val)),+,)
|
|
};
|
|
}
|
|
|
|
#[cfg(test)]
|
|
macro_rules! assert_approx_eq {
|
|
($a:expr, $b:expr) => ({
|
|
let (a, b) = (&$a, &$b);
|
|
assert!((*a - *b).abs() < 1.0e-6,
|
|
"{} is not approximately equal to {}", *a, *b);
|
|
})
|
|
}
|