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