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