From: Miguel Ojeda <ojeda@kernel.org>
To: "Miguel Ojeda" <ojeda@kernel.org>,
"Wedson Almeida Filho" <wedsonaf@gmail.com>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>
Cc: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org,
patches@lists.linux.dev, Niklas Mohrin <dev@niklasmohrin.de>
Subject: [PATCH v1 23/28] rust: std_vendor: add `dbg!` macro based on `std`'s one
Date: Thu, 10 Nov 2022 17:41:35 +0100 [thread overview]
Message-ID: <20221110164152.26136-24-ojeda@kernel.org> (raw)
In-Reply-To: <20221110164152.26136-1-ojeda@kernel.org>
From: Niklas Mohrin <dev@niklasmohrin.de>
The Rust standard library has a really handy macro, `dbg!` [1,2].
It prints the source location (filename and line) along with the raw
source code that is invoked with and the `Debug` representation
of the given expression, e.g.:
let a = 2;
let b = dbg!(a * 2) + 1;
// ^-- prints: [src/main.rs:2] a * 2 = 4
assert_eq!(b, 5);
Port the macro over to the `kernel` crate, using `pr_info!`
instead of `eprintln!`, inside a new module called `std_vendor`.
Since the source code for the macro is taken from the standard
library source (with only minor adjustments), the new file is
licensed under `Apache 2.0 OR MIT`, just like the original [3,4].
Link: https://doc.rust-lang.org/std/macro.dbg.html [1]
Link: https://github.com/rust-lang/rust/blob/master/library/std/src/macros.rs#L212 [2]
Link: https://github.com/rust-lang/rust/blob/master/library/std/Cargo.toml [3]
Link: https://github.com/rust-lang/rust/blob/master/COPYRIGHT [4]
Signed-off-by: Niklas Mohrin <dev@niklasmohrin.de>
[Reworded, adapted for upstream and applied latest changes]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
---
rust/kernel/lib.rs | 2 +
rust/kernel/prelude.rs | 2 +-
rust/kernel/std_vendor.rs | 160 ++++++++++++++++++++++++++++++++++++++
3 files changed, 163 insertions(+), 1 deletion(-)
create mode 100644 rust/kernel/std_vendor.rs
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index ffc6626a6d29..d6371c9c8453 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -26,6 +26,8 @@ mod allocator;
pub mod error;
pub mod prelude;
pub mod print;
+#[doc(hidden)]
+pub mod std_vendor;
pub mod str;
#[doc(hidden)]
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 89c2c9f4e7a7..345fc9075d1f 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -17,7 +17,7 @@ pub use alloc::{boxed::Box, vec::Vec};
pub use macros::{module, vtable};
-pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
+pub use super::{dbg, pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
pub use super::error::{code::*, Error, Result};
diff --git a/rust/kernel/std_vendor.rs b/rust/kernel/std_vendor.rs
new file mode 100644
index 000000000000..da57b4e521f4
--- /dev/null
+++ b/rust/kernel/std_vendor.rs
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: Apache-2.0 OR MIT
+
+//! The contents of this file come from the Rust standard library, hosted in
+//! the <https://github.com/rust-lang/rust> repository, licensed under
+//! "Apache-2.0 OR MIT" and adapted for kernel use. For copyright details,
+//! see <https://github.com/rust-lang/rust/blob/master/COPYRIGHT>.
+
+/// [`std::dbg`], but using [`pr_info`] instead of [`eprintln`].
+///
+/// Prints and returns the value of a given expression for quick and dirty
+/// debugging.
+///
+/// An example:
+///
+/// ```rust
+/// let a = 2;
+/// # #[allow(clippy::dbg_macro)]
+/// let b = dbg!(a * 2) + 1;
+/// // ^-- prints: [src/main.rs:2] a * 2 = 4
+/// assert_eq!(b, 5);
+/// ```
+///
+/// The macro works by using the `Debug` implementation of the type of
+/// the given expression to print the value with [`printk`] along with the
+/// source location of the macro invocation as well as the source code
+/// of the expression.
+///
+/// Invoking the macro on an expression moves and takes ownership of it
+/// before returning the evaluated expression unchanged. If the type
+/// of the expression does not implement `Copy` and you don't want
+/// to give up ownership, you can instead borrow with `dbg!(&expr)`
+/// for some expression `expr`.
+///
+/// The `dbg!` macro works exactly the same in release builds.
+/// This is useful when debugging issues that only occur in release
+/// builds or when debugging in release mode is significantly faster.
+///
+/// Note that the macro is intended as a debugging tool and therefore you
+/// should avoid having uses of it in version control for long periods
+/// (other than in tests and similar).
+///
+/// # Stability
+///
+/// The exact output printed by this macro should not be relied upon
+/// and is subject to future changes.
+///
+/// # Further examples
+///
+/// With a method call:
+///
+/// ```rust
+/// # #[allow(clippy::dbg_macro)]
+/// fn foo(n: usize) {
+/// if dbg!(n.checked_sub(4)).is_some() {
+/// // ...
+/// }
+/// }
+///
+/// foo(3)
+/// ```
+///
+/// This prints to the kernel log:
+///
+/// ```text,ignore
+/// [src/main.rs:4] n.checked_sub(4) = None
+/// ```
+///
+/// Naive factorial implementation:
+///
+/// ```rust
+/// # #[allow(clippy::dbg_macro)]
+/// # {
+/// fn factorial(n: u32) -> u32 {
+/// if dbg!(n <= 1) {
+/// dbg!(1)
+/// } else {
+/// dbg!(n * factorial(n - 1))
+/// }
+/// }
+///
+/// dbg!(factorial(4));
+/// # }
+/// ```
+///
+/// This prints to the kernel log:
+///
+/// ```text,ignore
+/// [src/main.rs:3] n <= 1 = false
+/// [src/main.rs:3] n <= 1 = false
+/// [src/main.rs:3] n <= 1 = false
+/// [src/main.rs:3] n <= 1 = true
+/// [src/main.rs:4] 1 = 1
+/// [src/main.rs:5] n * factorial(n - 1) = 2
+/// [src/main.rs:5] n * factorial(n - 1) = 6
+/// [src/main.rs:5] n * factorial(n - 1) = 24
+/// [src/main.rs:11] factorial(4) = 24
+/// ```
+///
+/// The `dbg!(..)` macro moves the input:
+///
+/// ```ignore
+/// /// A wrapper around `usize` which importantly is not Copyable.
+/// #[derive(Debug)]
+/// struct NoCopy(usize);
+///
+/// let a = NoCopy(42);
+/// let _ = dbg!(a); // <-- `a` is moved here.
+/// let _ = dbg!(a); // <-- `a` is moved again; error!
+/// ```
+///
+/// You can also use `dbg!()` without a value to just print the
+/// file and line whenever it's reached.
+///
+/// Finally, if you want to `dbg!(..)` multiple values, it will treat them as
+/// a tuple (and return it, too):
+///
+/// ```
+/// # #[allow(clippy::dbg_macro)]
+/// assert_eq!(dbg!(1usize, 2u32), (1, 2));
+/// ```
+///
+/// However, a single argument with a trailing comma will still not be treated
+/// as a tuple, following the convention of ignoring trailing commas in macro
+/// invocations. You can use a 1-tuple directly if you need one:
+///
+/// ```
+/// # #[allow(clippy::dbg_macro)]
+/// # {
+/// assert_eq!(1, dbg!(1u32,)); // trailing comma ignored
+/// assert_eq!((1,), dbg!((1u32,))); // 1-tuple
+/// # }
+/// ```
+///
+/// [`std::dbg`]: https://doc.rust-lang.org/std/macro.dbg.html
+/// [`eprintln`]: https://doc.rust-lang.org/std/macro.eprintln.html
+/// [`printk`]: https://www.kernel.org/doc/html/latest/core-api/printk-basics.html
+#[macro_export]
+macro_rules! dbg {
+ // NOTE: We cannot use `concat!` to make a static string as a format argument
+ // of `pr_info!` because `file!` could contain a `{` or
+ // `$val` expression could be a block (`{ .. }`), in which case the `pr_info!`
+ // will be malformed.
+ () => {
+ $crate::pr_info!("[{}:{}]\n", ::core::file!(), ::core::line!())
+ };
+ ($val:expr $(,)?) => {
+ // Use of `match` here is intentional because it affects the lifetimes
+ // of temporaries - https://stackoverflow.com/a/48732525/1063961
+ match $val {
+ tmp => {
+ $crate::pr_info!("[{}:{}] {} = {:#?}\n",
+ ::core::file!(), ::core::line!(), ::core::stringify!($val), &tmp);
+ tmp
+ }
+ }
+ };
+ ($($val:expr),+ $(,)?) => {
+ ($($crate::dbg!($val)),+,)
+ };
+}
--
2.38.1
next prev parent reply other threads:[~2022-11-10 16:44 UTC|newest]
Thread overview: 68+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-11-10 16:41 [PATCH v1 00/28] Rust core additions Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 01/28] rust: prelude: split re-exports into groups Miguel Ojeda
2022-11-10 18:05 ` Boqun Feng
2022-11-14 14:40 ` Wei Liu
2022-11-10 16:41 ` [PATCH v1 02/28] rust: print: add more `pr_*!` levels Miguel Ojeda
2022-11-10 18:12 ` Boqun Feng
2022-11-14 14:40 ` Wei Liu
2022-11-14 15:01 ` Sergio González Collado
2022-11-10 16:41 ` [PATCH v1 03/28] rust: print: add `pr_cont!` macro Miguel Ojeda
2022-11-14 14:40 ` Wei Liu
2022-11-14 15:04 ` Sergio González Collado
2022-11-10 16:41 ` [PATCH v1 04/28] rust: samples: add `rust_print` example Miguel Ojeda
2022-11-11 9:40 ` Finn Behrens
2022-11-11 17:31 ` Miguel Ojeda
2022-11-14 14:41 ` Wei Liu
2022-11-21 22:51 ` Sergio González Collado
2022-11-10 16:41 ` [PATCH v1 05/28] rust: macros: add `concat_idents!` proc macro Miguel Ojeda
2022-11-11 9:25 ` Finn Behrens
2022-11-14 14:26 ` Gary Guo
2022-11-14 14:39 ` Björn Roy Baron
2022-11-14 17:22 ` Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 06/28] rust: macros: add `#[vtable]` " Miguel Ojeda
2022-11-14 15:06 ` Sergio González Collado
2022-11-10 16:41 ` [PATCH v1 07/28] rust: macros: take string literals in `module!` Miguel Ojeda
2022-11-14 14:47 ` Wei Liu
2022-11-14 16:46 ` Miguel Ojeda
2022-11-14 17:25 ` Wei Liu
2022-11-10 16:41 ` [PATCH v1 08/28] rust: error: declare errors using macro Miguel Ojeda
2022-11-14 14:28 ` Gary Guo
2022-11-10 16:41 ` [PATCH v1 09/28] rust: error: add codes from `errno-base.h` Miguel Ojeda
2022-11-14 14:29 ` Gary Guo
2022-11-10 16:41 ` [PATCH v1 10/28] rust: error: add `From` implementations for `Error` Miguel Ojeda
2022-11-11 9:50 ` Finn Behrens
2022-11-10 16:41 ` [PATCH v1 11/28] rust: prelude: add `error::code::*` constant items Miguel Ojeda
2022-11-14 14:32 ` Gary Guo
2022-11-10 16:41 ` [PATCH v1 12/28] rust: alloc: add `RawVec::try_with_capacity_in()` constructor Miguel Ojeda
2022-11-14 14:34 ` Gary Guo
2022-11-10 16:41 ` [PATCH v1 13/28] rust: alloc: add `Vec::try_with_capacity{,_in}()` constructors Miguel Ojeda
2022-11-14 14:35 ` Gary Guo
2022-11-10 16:41 ` [PATCH v1 14/28] rust: str: add `BStr` type Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 15/28] rust: str: add `b_str!` macro Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 16/28] rust: str: add `CStr` type Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 17/28] rust: str: implement several traits for `CStr` Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 18/28] rust: str: add `CStr` unit tests Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 19/28] rust: str: add `c_str!` macro Miguel Ojeda
2022-11-14 14:39 ` Gary Guo
2022-11-14 18:28 ` Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 20/28] rust: str: add `Formatter` type Miguel Ojeda
2022-11-14 14:42 ` Gary Guo
2022-11-10 16:41 ` [PATCH v1 21/28] rust: str: add `CString` type Miguel Ojeda
2022-11-14 14:53 ` Gary Guo
2022-11-10 16:41 ` [PATCH v1 22/28] rust: str: add `fmt!` macro Miguel Ojeda
2022-11-14 14:58 ` Gary Guo
2022-11-10 16:41 ` Miguel Ojeda [this message]
2022-11-10 18:01 ` [PATCH v1 23/28] rust: std_vendor: add `dbg!` macro based on `std`'s one Boqun Feng
2022-11-10 19:14 ` Miguel Ojeda
2022-11-10 19:16 ` Boqun Feng
2022-11-10 19:20 ` Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 24/28] rust: static_assert: add `static_assert!` macro Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 25/28] rust: add `build_error` crate Miguel Ojeda
2022-11-14 14:30 ` Wei Liu
2022-11-14 18:22 ` Miguel Ojeda
2022-11-14 21:06 ` Wei Liu
2022-11-10 16:41 ` [PATCH v1 26/28] rust: build_assert: add `build_{error,assert}!` macros Miguel Ojeda
2022-11-10 16:41 ` [PATCH v1 27/28] rust: types: add `Either` type Miguel Ojeda
2022-11-14 14:32 ` Wei Liu
2022-11-10 16:41 ` [PATCH v1 28/28] rust: types: add `Opaque` type Miguel Ojeda
2022-11-14 15:03 ` Gary Guo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221110164152.26136-24-ojeda@kernel.org \
--to=ojeda@kernel.org \
--cc=alex.gaynor@gmail.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dev@niklasmohrin.de \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=patches@lists.linux.dev \
--cc=rust-for-linux@vger.kernel.org \
--cc=wedsonaf@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).