]>
Commit | Line | Data |
---|---|---|
bee16889 NM |
1 | // SPDX-License-Identifier: Apache-2.0 OR MIT |
2 | ||
3 | //! The contents of this file come from the Rust standard library, hosted in | |
4 | //! the <https://github.com/rust-lang/rust> repository, licensed under | |
5 | //! "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 dirty | |
11 | /// debugging. | |
12 | /// | |
13 | /// An example: | |
14 | /// | |
15 | /// ```rust | |
16 | /// let a = 2; | |
17 | /// # #[allow(clippy::dbg_macro)] | |
18 | /// let b = dbg!(a * 2) + 1; | |
19 | /// // ^-- prints: [src/main.rs:2] a * 2 = 4 | |
20 | /// assert_eq!(b, 5); | |
21 | /// ``` | |
22 | /// | |
23 | /// The macro works by using the `Debug` implementation of the type of | |
24 | /// the given expression to print the value with [`printk`] along with the | |
25 | /// source location of the macro invocation as well as the source code | |
26 | /// of the expression. | |
27 | /// | |
28 | /// Invoking the macro on an expression moves and takes ownership of it | |
29 | /// before returning the evaluated expression unchanged. If the type | |
30 | /// of the expression does not implement `Copy` and you don't want | |
31 | /// 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 release | |
36 | /// builds or when debugging in release mode is significantly faster. | |
37 | /// | |
38 | /// Note that the macro is intended as a temporary debugging tool to be | |
39 | /// used during development. Therefore, avoid committing `dbg!` macro | |
40 | /// 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 | /// # Stability | |
46 | /// | |
47 | /// The exact output printed by this macro should not be relied upon | |
48 | /// and is subject to future changes. | |
49 | /// | |
50 | /// # Further examples | |
51 | /// | |
52 | /// With a method call: | |
53 | /// | |
54 | /// ```rust | |
55 | /// # #[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,ignore | |
68 | /// [src/main.rs:4] n.checked_sub(4) = None | |
69 | /// ``` | |
70 | /// | |
71 | /// Naive factorial implementation: | |
72 | /// | |
73 | /// ```rust | |
74 | /// # #[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,ignore | |
91 | /// [src/main.rs:3] n <= 1 = false | |
92 | /// [src/main.rs:3] n <= 1 = false | |
93 | /// [src/main.rs:3] n <= 1 = false | |
94 | /// [src/main.rs:3] n <= 1 = true | |
95 | /// [src/main.rs:4] 1 = 1 | |
96 | /// [src/main.rs:5] n * factorial(n - 1) = 2 | |
97 | /// [src/main.rs:5] n * factorial(n - 1) = 6 | |
98 | /// [src/main.rs:5] n * factorial(n - 1) = 24 | |
99 | /// [src/main.rs:11] 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 | /// # #[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 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 | /// # #[allow(clippy::dbg_macro)] | |
131 | /// # { | |
132 | /// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored | |
133 | /// assert_eq!((1,), dbg!((1u32,))); // 1-tuple | |
134 | /// # } | |
135 | /// ``` | |
136 | /// | |
137 | /// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html | |
138 | /// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html | |
139 | /// [`printk`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html | |
3ed03f4d MO |
140 | /// [`pr_info`]: crate::pr_info! |
141 | /// [`pr_debug`]: crate::pr_debug! | |
bee16889 NM |
142 | #[macro_export] |
143 | macro_rules! dbg { | |
144 | // NOTE: We cannot use `concat!` to make a static string as a format argument | |
145 | // of `pr_info!` because `file!` could contain a `{` or | |
146 | // `$val` expression could be a block (`{ .. }`), in which case the `pr_info!` | |
147 | // will be malformed. | |
148 | () => { | |
ea175b2d | 149 | $crate::pr_info!("[{}:{}:{}]\n", ::core::file!(), ::core::line!(), ::core::column!()) |
bee16889 NM |
150 | }; |
151 | ($val:expr $(,)?) => { | |
152 | // Use of `match` here is intentional because it affects the lifetimes | |
153 | // of temporaries - https://stackoverflow.com/a/48732525/1063961 | |
154 | match $val { | |
155 | tmp => { | |
ea175b2d RN |
156 | $crate::pr_info!("[{}:{}:{}] {} = {:#?}\n", |
157 | ::core::file!(), ::core::line!(), ::core::column!(), | |
158 | ::core::stringify!($val), &tmp); | |
bee16889 NM |
159 | tmp |
160 | } | |
161 | } | |
162 | }; | |
163 | ($($val:expr),+ $(,)?) => { | |
164 | ($($crate::dbg!($val)),+,) | |
165 | }; | |
166 | } |