167 lines · rust
1// SPDX-License-Identifier: Apache-2.0 OR MIT2 3//! The contents of this file come from the Rust standard library, hosted in4//! the <https://github.com/rust-lang/rust> repository, licensed under5//! "Apache-2.0 OR MIT" and adapted for kernel use. For copyright details,6//! see <https://github.com/rust-lang/rust/blob/master/COPYRIGHT>.7 8/// [`std::dbg`], but using [`pr_info`] instead of [`eprintln`].9///10/// Prints and returns the value of a given expression for quick and dirty11/// debugging.12///13/// An example:14///15/// ```rust16/// let a = 2;17/// # #[allow(clippy::dbg_macro)]18/// let b = dbg!(a * 2) + 1;19/// // ^-- prints: [src/main.rs:2] a * 2 = 420/// assert_eq!(b, 5);21/// ```22///23/// The macro works by using the `Debug` implementation of the type of24/// the given expression to print the value with [`printk`] along with the25/// source location of the macro invocation as well as the source code26/// of the expression.27///28/// Invoking the macro on an expression moves and takes ownership of it29/// before returning the evaluated expression unchanged. If the type30/// of the expression does not implement `Copy` and you don't want31/// to give up ownership, you can instead borrow with `dbg!(&expr)`32/// for some expression `expr`.33///34/// The `dbg!` macro works exactly the same in release builds.35/// This is useful when debugging issues that only occur in release36/// builds or when debugging in release mode is significantly faster.37///38/// Note that the macro is intended as a temporary debugging tool to be39/// used during development. Therefore, avoid committing `dbg!` macro40/// invocations into the kernel tree.41///42/// For debug output that is intended to be kept in the kernel tree,43/// use [`pr_debug`] and similar facilities instead.44///45/// # Stability46///47/// The exact output printed by this macro should not be relied upon48/// and is subject to future changes.49///50/// # Further examples51///52/// With a method call:53///54/// ```rust55/// # #[allow(clippy::dbg_macro)]56/// fn foo(n: usize) {57/// if dbg!(n.checked_sub(4)).is_some() {58/// // ...59/// }60/// }61///62/// foo(3)63/// ```64///65/// This prints to the kernel log:66///67/// ```text,ignore68/// [src/main.rs:4] n.checked_sub(4) = None69/// ```70///71/// Naive factorial implementation:72///73/// ```rust74/// # #[allow(clippy::dbg_macro)]75/// # {76/// fn factorial(n: u32) -> u32 {77/// if dbg!(n <= 1) {78/// dbg!(1)79/// } else {80/// dbg!(n * factorial(n - 1))81/// }82/// }83///84/// dbg!(factorial(4));85/// # }86/// ```87///88/// This prints to the kernel log:89///90/// ```text,ignore91/// [src/main.rs:3] n <= 1 = false92/// [src/main.rs:3] n <= 1 = false93/// [src/main.rs:3] n <= 1 = false94/// [src/main.rs:3] n <= 1 = true95/// [src/main.rs:4] 1 = 196/// [src/main.rs:5] n * factorial(n - 1) = 297/// [src/main.rs:5] n * factorial(n - 1) = 698/// [src/main.rs:5] n * factorial(n - 1) = 2499/// [src/main.rs:11] factorial(4) = 24100/// ```101///102/// The `dbg!(..)` macro moves the input:103///104/// ```ignore105/// /// A wrapper around `usize` which importantly is not Copyable.106/// #[derive(Debug)]107/// struct NoCopy(usize);108///109/// let a = NoCopy(42);110/// let _ = dbg!(a); // <-- `a` is moved here.111/// let _ = dbg!(a); // <-- `a` is moved again; error!112/// ```113///114/// You can also use `dbg!()` without a value to just print the115/// file and line whenever it's reached.116///117/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as118/// a tuple (and return it, too):119///120/// ```121/// # #[allow(clippy::dbg_macro)]122/// assert_eq!(dbg!(1usize, 2u32), (1, 2));123/// ```124///125/// However, a single argument with a trailing comma will still not be treated126/// as a tuple, following the convention of ignoring trailing commas in macro127/// invocations. You can use a 1-tuple directly if you need one:128///129/// ```130/// # #[allow(clippy::dbg_macro)]131/// # {132/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored133/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple134/// # }135/// ```136///137/// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html138/// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html139/// [`printk`]: https://docs.kernel.org/core-api/printk-basics.html140/// [`pr_info`]: crate::pr_info!141/// [`pr_debug`]: crate::pr_debug!142#[macro_export]143macro_rules! dbg {144 // NOTE: We cannot use `concat!` to make a static string as a format argument145 // of `pr_info!` because `file!` could contain a `{` or146 // `$val` expression could be a block (`{ .. }`), in which case the `pr_info!`147 // will be malformed.148 () => {149 $crate::pr_info!("[{}:{}:{}]\n", ::core::file!(), ::core::line!(), ::core::column!())150 };151 ($val:expr $(,)?) => {152 // Use of `match` here is intentional because it affects the lifetimes153 // of temporaries - https://stackoverflow.com/a/48732525/1063961154 match $val {155 tmp => {156 $crate::pr_info!("[{}:{}:{}] {} = {:#?}\n",157 ::core::file!(), ::core::line!(), ::core::column!(),158 ::core::stringify!($val), &tmp);159 tmp160 }161 }162 };163 ($($val:expr),+ $(,)?) => {164 ($($crate::dbg!($val)),+,)165 };166}167