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