|
| 1 | +// SPDX-License-Identifier: Apache-2.0 OR MIT |
| 2 | + |
| 3 | +//! The contents of this file come from the Rust standard library, hosted in the |
| 4 | +//! <https://github.com/rust-lang/rust> repository. For copyright details, see |
| 5 | +//! <https://github.com/rust-lang/rust/blob/master/COPYRIGHT>. |
| 6 | +
|
| 7 | +/// [`std::dbg`], but using [`pr_info`] instead of [`eprintln`]. |
| 8 | +/// |
| 9 | +/// Prints and returns the value of a given expression for quick and dirty |
| 10 | +/// debugging. |
| 11 | +/// |
| 12 | +/// An example: |
| 13 | +/// |
| 14 | +/// ```rust |
| 15 | +/// let a = 2; |
| 16 | +/// let b = dbg!(a * 2) + 1; |
| 17 | +/// // ^-- prints: [src/main.rs:2] a * 2 = 4 |
| 18 | +/// assert_eq!(b, 5); |
| 19 | +/// ``` |
| 20 | +/// |
| 21 | +/// The macro works by using the `Debug` implementation of the type of |
| 22 | +/// the given expression to print the value with [`printk`] along with the |
| 23 | +/// source location of the macro invocation as well as the source code |
| 24 | +/// of the expression. |
| 25 | +/// |
| 26 | +/// Invoking the macro on an expression moves and takes ownership of it |
| 27 | +/// before returning the evaluated expression unchanged. If the type |
| 28 | +/// of the expression does not implement `Copy` and you don't want |
| 29 | +/// to give up ownership, you can instead borrow with `dbg!(&expr)` |
| 30 | +/// for some expression `expr`. |
| 31 | +/// |
| 32 | +/// The `dbg!` macro works exactly the same in release builds. |
| 33 | +/// This is useful when debugging issues that only occur in release |
| 34 | +/// builds or when debugging in release mode is significantly faster. |
| 35 | +/// |
| 36 | +/// Note that the macro is intended as a debugging tool and therefore you |
| 37 | +/// should avoid having uses of it in version control for long periods |
| 38 | +/// (other than in tests and similar). |
| 39 | +/// |
| 40 | +/// # Stability |
| 41 | +/// |
| 42 | +/// The exact output printed by this macro should not be relied upon |
| 43 | +/// and is subject to future changes. |
| 44 | +/// |
| 45 | +/// # Further examples |
| 46 | +/// |
| 47 | +/// With a method call: |
| 48 | +/// |
| 49 | +/// ```rust |
| 50 | +/// fn foo(n: usize) { |
| 51 | +/// if let Some(_) = dbg!(n.checked_sub(4)) { |
| 52 | +/// // ... |
| 53 | +/// } |
| 54 | +/// } |
| 55 | +/// |
| 56 | +/// foo(3) |
| 57 | +/// ``` |
| 58 | +/// |
| 59 | +/// This prints to the kernel log: |
| 60 | +/// |
| 61 | +/// ```text,ignore |
| 62 | +/// [src/main.rs:4] n.checked_sub(4) = None |
| 63 | +/// ``` |
| 64 | +/// |
| 65 | +/// Naive factorial implementation: |
| 66 | +/// |
| 67 | +/// ```rust |
| 68 | +/// fn factorial(n: u32) -> u32 { |
| 69 | +/// if dbg!(n <= 1) { |
| 70 | +/// dbg!(1) |
| 71 | +/// } else { |
| 72 | +/// dbg!(n * factorial(n - 1)) |
| 73 | +/// } |
| 74 | +/// } |
| 75 | +/// |
| 76 | +/// dbg!(factorial(4)); |
| 77 | +/// ``` |
| 78 | +/// |
| 79 | +/// This prints to the kernel log: |
| 80 | +/// |
| 81 | +/// ```text,ignore |
| 82 | +/// [src/main.rs:3] n <= 1 = false |
| 83 | +/// [src/main.rs:3] n <= 1 = false |
| 84 | +/// [src/main.rs:3] n <= 1 = false |
| 85 | +/// [src/main.rs:3] n <= 1 = true |
| 86 | +/// [src/main.rs:4] 1 = 1 |
| 87 | +/// [src/main.rs:5] n * factorial(n - 1) = 2 |
| 88 | +/// [src/main.rs:5] n * factorial(n - 1) = 6 |
| 89 | +/// [src/main.rs:5] n * factorial(n - 1) = 24 |
| 90 | +/// [src/main.rs:11] factorial(4) = 24 |
| 91 | +/// ``` |
| 92 | +/// |
| 93 | +/// The `dbg!(..)` macro moves the input: |
| 94 | +/// |
| 95 | +/// ```compile_fail |
| 96 | +/// /// A wrapper around `usize` which importantly is not Copyable. |
| 97 | +/// #[derive(Debug)] |
| 98 | +/// struct NoCopy(usize); |
| 99 | +/// |
| 100 | +/// let a = NoCopy(42); |
| 101 | +/// let _ = dbg!(a); // <-- `a` is moved here. |
| 102 | +/// let _ = dbg!(a); // <-- `a` is moved again; error! |
| 103 | +/// ``` |
| 104 | +/// |
| 105 | +/// You can also use `dbg!()` without a value to just print the |
| 106 | +/// file and line whenever it's reached. |
| 107 | +/// |
| 108 | +/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as |
| 109 | +/// a tuple (and return it, too): |
| 110 | +/// |
| 111 | +/// ``` |
| 112 | +/// assert_eq!(dbg!(1usize, 2u32), (1, 2)); |
| 113 | +/// ``` |
| 114 | +/// |
| 115 | +/// However, a single argument with a trailing comma will still not be treated |
| 116 | +/// as a tuple, following the convention of ignoring trailing commas in macro |
| 117 | +/// invocations. You can use a 1-tuple directly if you need one: |
| 118 | +/// |
| 119 | +/// ``` |
| 120 | +/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored |
| 121 | +/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple |
| 122 | +/// ``` |
| 123 | +/// |
| 124 | +/// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html |
| 125 | +/// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html |
| 126 | +/// [`printk`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html |
| 127 | +#[macro_export] |
| 128 | +macro_rules! dbg { |
| 129 | + // NOTE: We cannot use `concat!` to make a static string as a format argument |
| 130 | + // of `pr_info!` because `file!` could contain a `{` or |
| 131 | + // `$val` expression could be a block (`{ .. }`), in which case the `pr_info!` |
| 132 | + // will be malformed. |
| 133 | + () => { |
| 134 | + $crate::pr_info!("[{}:{}]\n", ::core::file!(), ::core::line!()) |
| 135 | + }; |
| 136 | + ($val:expr $(,)?) => { |
| 137 | + // Use of `match` here is intentional because it affects the lifetimes |
| 138 | + // of temporaries - https://stackoverflow.com/a/48732525/1063961 |
| 139 | + match $val { |
| 140 | + tmp => { |
| 141 | + $crate::pr_info!("[{}:{}] {} = {:#?}\n", |
| 142 | + ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp); |
| 143 | + tmp |
| 144 | + } |
| 145 | + } |
| 146 | + }; |
| 147 | + ($($val:expr),+ $(,)?) => { |
| 148 | + ($($crate::dbg!($val)),+,) |
| 149 | + }; |
| 150 | +} |
0 commit comments