mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-07-05 21:35:46 +02:00

commit 1f9ed172545687e5c04c77490a45896be6d2e459 upstream. In Rust, it is possible to `allow` particular warnings (diagnostics, lints) locally, making the compiler ignore instances of a given warning within a given function, module, block, etc. It is similar to `#pragma GCC diagnostic push` + `ignored` + `pop` in C: #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-function" static void f(void) {} #pragma GCC diagnostic pop But way less verbose: #[allow(dead_code)] fn f() {} By that virtue, it makes it possible to comfortably enable more diagnostics by default (i.e. outside `W=` levels) that may have some false positives but that are otherwise quite useful to keep enabled to catch potential mistakes. The `#[expect(...)]` attribute [1] takes this further, and makes the compiler warn if the diagnostic was _not_ produced. For instance, the following will ensure that, when `f()` is called somewhere, we will have to remove the attribute: #[expect(dead_code)] fn f() {} If we do not, we get a warning from the compiler: warning: this lint expectation is unfulfilled --> x.rs:3:10 | 3 | #[expect(dead_code)] | ^^^^^^^^^ | = note: `#[warn(unfulfilled_lint_expectations)]` on by default This means that `expect`s do not get forgotten when they are not needed. See the next commit for more details, nuances on its usage and documentation on the feature. The attribute requires the `lint_reasons` [2] unstable feature, but it is becoming stable in 1.81.0 (to be released on 2024-09-05) and it has already been useful to clean things up in this patch series, finding cases where the `allow`s should not have been there. Thus, enable `lint_reasons` and convert some of our `allow`s to `expect`s where possible. This feature was also an example of the ongoing collaboration between Rust and the kernel -- we tested it in the kernel early on and found an issue that was quickly resolved [3]. Cc: Fridtjof Stoldt <xfrednet@gmail.com> Cc: Urgau <urgau@numericable.fr> Link: https://rust-lang.github.io/rfcs/2383-lint-reasons.html#expect-lint-attribute [1] Link: https://github.com/rust-lang/rust/issues/54503 [2] Link: https://github.com/rust-lang/rust/issues/114557 [3] Reviewed-by: Alice Ryhl <aliceryhl@google.com> Reviewed-by: Trevor Gross <tmgross@umich.edu> Tested-by: Gary Guo <gary@garyguo.net> Reviewed-by: Gary Guo <gary@garyguo.net> Link: https://lore.kernel.org/r/20240904204347.168520-18-ojeda@kernel.org Signed-off-by: Miguel Ojeda <ojeda@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
169 lines
5.2 KiB
Rust
169 lines
5.2 KiB
Rust
// SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
|
|
//! Rust standard library vendored code.
|
|
//!
|
|
//! 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;
|
|
/// # #[expect(clippy::disallowed_macros)]
|
|
/// 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 temporary debugging tool to be
|
|
/// used during development. Therefore, avoid committing `dbg!` macro
|
|
/// invocations into the kernel tree.
|
|
///
|
|
/// For debug output that is intended to be kept in the kernel tree,
|
|
/// use [`pr_debug`] and similar facilities instead.
|
|
///
|
|
/// # 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
|
|
/// # #[expect(clippy::disallowed_macros)]
|
|
/// 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
|
|
/// # #[expect(clippy::disallowed_macros)]
|
|
/// # {
|
|
/// 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):
|
|
///
|
|
/// ```
|
|
/// # #![expect(clippy::disallowed_macros)]
|
|
/// 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:
|
|
///
|
|
/// ```
|
|
/// # #[expect(clippy::disallowed_macros)]
|
|
/// # {
|
|
/// 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://docs.kernel.org/core-api/printk-basics.html
|
|
/// [`pr_info`]: crate::pr_info!
|
|
/// [`pr_debug`]: crate::pr_debug!
|
|
#[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!(), ::core::column!())
|
|
};
|
|
($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::column!(),
|
|
::core::stringify!($val), &tmp);
|
|
tmp
|
|
}
|
|
}
|
|
};
|
|
($($val:expr),+ $(,)?) => {
|
|
($($crate::dbg!($val)),+,)
|
|
};
|
|
}
|