Skip to content

Commit 0d6f2a0

Browse files
authored
Merge pull request #483 from niklasmohrin/dbg-macro
Add `dbg!` macro from `std`
2 parents 238b5b6 + 1611373 commit 0d6f2a0

File tree

3 files changed

+153
-1
lines changed

3 files changed

+153
-1
lines changed

rust/kernel/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ pub mod prelude;
6767
pub mod print;
6868
pub mod random;
6969
mod static_assert;
70+
#[doc(hidden)]
71+
pub mod std_vendor;
7072
pub mod sync;
7173

7274
#[cfg(any(CONFIG_SYSCTL, doc))]

rust/kernel/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub use macros::{module, module_misc_device};
1919

2020
pub use super::build_assert;
2121

22-
pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
22+
pub use super::{dbg, pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
2323

2424
pub use super::static_assert;
2525

rust/kernel/std_vendor.rs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
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

Comments
 (0)