Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

rust: rework `build_assert!` documentation

Add a detailed comparison and recommendation of the three types of
build-time assertion macro as module documentation (and un-hide the module
to render them).

The documentation on the macro themselves are simplified to only cover the
scenarios where they should be used; links to the module documentation is
added instead.

Reviewed-by: Yury Norov <ynorov@nvidia.com>
Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Alexandre Courbot <acourbot@nvidia.com>
Reviewed-by: Alice Ryhl <aliceryhl@google.com>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
Link: https://patch.msgid.link/20260319121653.2975748-4-gary@kernel.org
[ Added periods on comments. - Miguel ]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>

authored by

Gary Guo and committed by
Miguel Ojeda
889c8c93 560a7a9b

+94 -30
+94 -29
rust/kernel/build_assert.rs
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 3 3 //! Various assertions that happen during build-time. 4 + //! 5 + //! There are three types of build-time assertions that you can use: 6 + //! - [`static_assert!`] 7 + //! - [`const_assert!`] 8 + //! - [`build_assert!`] 9 + //! 10 + //! The ones towards the bottom of the list are more expressive, while the ones towards the top of 11 + //! the list are more robust and trigger earlier in the compilation pipeline. Therefore, you should 12 + //! prefer the ones towards the top of the list wherever possible. 13 + //! 14 + //! # Choosing the correct assertion 15 + //! 16 + //! If you're asserting outside any bodies (e.g. initializers or function bodies), you should use 17 + //! [`static_assert!`] as it is the only assertion that can be used in that context. 18 + //! 19 + //! Inside bodies, if your assertion condition does not depend on any variable or generics, you 20 + //! should use [`static_assert!`]. If the condition depends on generics, but not variables 21 + //! (including function arguments), you should use [`const_assert!`]. Otherwise, use 22 + //! [`build_assert!`]. The same is true regardless if the function is `const fn`. 23 + //! 24 + //! ``` 25 + //! // Outside any bodies. 26 + //! static_assert!(core::mem::size_of::<u8>() == 1); 27 + //! // `const_assert!` and `build_assert!` cannot be used here, they will fail to compile. 28 + //! 29 + //! #[inline(always)] 30 + //! fn foo<const N: usize>(v: usize) { 31 + //! static_assert!(core::mem::size_of::<u8>() == 1); // Preferred. 32 + //! const_assert!(core::mem::size_of::<u8>() == 1); // Discouraged. 33 + //! build_assert!(core::mem::size_of::<u8>() == 1); // Discouraged. 34 + //! 35 + //! // `static_assert!(N > 1);` is not allowed. 36 + //! const_assert!(N > 1); // Preferred. 37 + //! build_assert!(N > 1); // Discouraged. 38 + //! 39 + //! // `static_assert!(v > 1);` is not allowed. 40 + //! // `const_assert!(v > 1);` is not allowed. 41 + //! build_assert!(v > 1); // Works. 42 + //! } 43 + //! ``` 44 + //! 45 + //! # Detailed behavior 46 + //! 47 + //! `static_assert!()` is equivalent to `static_assert` in C. It requires `expr` to be a constant 48 + //! expression. This expression cannot refer to any generics. A `static_assert!(expr)` in a program 49 + //! is always evaluated, regardless if the function it appears in is used or not. This is also the 50 + //! only usable assertion outside a body. 51 + //! 52 + //! `const_assert!()` has no direct C equivalence. It is a more powerful version of 53 + //! `static_assert!()`, where it may refer to generics in a function. Note that due to the ability 54 + //! to refer to generics, the assertion is tied to a specific instance of a function. So if it is 55 + //! used in a generic function that is not instantiated, the assertion will not be checked. For this 56 + //! reason, `static_assert!()` is preferred wherever possible. 57 + //! 58 + //! `build_assert!()` is equivalent to `BUILD_BUG_ON`. It is even more powerful than 59 + //! `const_assert!()` because it can be used to check tautologies that depend on runtime value (this 60 + //! is the same as `BUILD_BUG_ON`). However, the assertion failure mechanism can possibly be 61 + //! undefined symbols and linker errors, it is not developer friendly to debug, so it is recommended 62 + //! to avoid it and prefer other two assertions where possible. 63 + 64 + pub use crate::{ 65 + build_assert, 66 + build_error, 67 + const_assert, 68 + static_assert, // 69 + }; 4 70 5 71 #[doc(hidden)] 6 72 pub use build_error::build_error; ··· 80 14 /// due to constness limitations of the [`assert!`] macro. 81 15 /// 82 16 /// The feature may be added to Rust in the future: see [RFC 2790]. 17 + /// 18 + /// You cannot refer to generics or variables with [`static_assert!`]. If you need to refer to 19 + /// generics, use [`const_assert!`]; if you need to refer to variables, use [`build_assert!`]. See 20 + /// the [module documentation](self). 83 21 /// 84 22 /// [`_Static_assert`]: https://en.cppreference.com/w/c/language/_Static_assert 85 23 /// [`static_assert`]: https://en.cppreference.com/w/cpp/language/static_assert ··· 116 46 /// This is a more powerful version of [`static_assert!`] that can refer to generics inside 117 47 /// functions or implementation blocks. However, it also has a limitation where it can only appear 118 48 /// in places where statements can appear; for example, you cannot use it as an item in the module. 49 + /// 50 + /// [`static_assert!`] should be preferred if no generics are referred to in the condition. You 51 + /// cannot refer to variables with [`const_assert!`] (even inside `const fn`); if you need the 52 + /// capability, use [`build_assert!`]. See the [module documentation](self). 119 53 /// 120 54 /// # Examples 121 55 /// ··· 172 98 /// will panic. If the compiler or optimizer cannot guarantee the condition will 173 99 /// be evaluated to `true`, a build error will be triggered. 174 100 /// 175 - /// [`static_assert!`] should be preferred to `build_assert!` whenever possible. 176 - /// 177 - /// # Examples 178 - /// 179 - /// These examples show that different types of [`assert!`] will trigger errors 180 - /// at different stage of compilation. It is preferred to err as early as 181 - /// possible, so [`static_assert!`] should be used whenever possible. 182 - /// ```ignore 183 - /// fn foo() { 184 - /// static_assert!(1 > 1); // Compile-time error 185 - /// build_assert!(1 > 1); // Build-time error 186 - /// assert!(1 > 1); // Run-time error 187 - /// } 188 - /// ``` 189 - /// 190 - /// When the condition refers to generic parameters or parameters of an inline function, 191 - /// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario. 192 - /// ``` 193 - /// fn foo<const N: usize>() { 194 - /// // `static_assert!(N > 1);` is not allowed 195 - /// build_assert!(N > 1); // Build-time check 196 - /// assert!(N > 1); // Run-time check 197 - /// } 198 - /// ``` 199 - /// 200 101 /// When a condition depends on a function argument, the function must be annotated with 201 102 /// `#[inline(always)]`. Without this attribute, the compiler may choose to not inline the 202 103 /// function, preventing it from optimizing out the error path. 104 + /// 105 + /// If the assertion condition does not depend on any variables or generics, you should use 106 + /// [`static_assert!`]. If the assertion condition does not depend on variables, but does depend on 107 + /// generics, you should use [`const_assert!`]. See the [module documentation](self). 108 + /// 109 + /// # Examples 110 + /// 203 111 /// ``` 204 - /// #[inline(always)] 112 + /// #[inline(always)] // Important. 205 113 /// fn bar(n: usize) { 206 - /// // `static_assert!(n > 1);` is not allowed 207 - /// build_assert!(n > 1); // Build-time check 208 - /// assert!(n > 1); // Run-time check 114 + /// build_assert!(n > 1); 209 115 /// } 116 + /// 117 + /// fn foo() { 118 + /// bar(2); 119 + /// } 120 + /// 121 + /// #[inline(always)] // Important. 122 + /// const fn const_bar(n: usize) { 123 + /// build_assert!(n > 1); 124 + /// } 125 + /// 126 + /// const _: () = const_bar(2); 210 127 /// ``` 211 128 #[macro_export] 212 129 macro_rules! build_assert {
-1
rust/kernel/lib.rs
··· 73 73 #[cfg(CONFIG_BLOCK)] 74 74 pub mod block; 75 75 pub mod bug; 76 - #[doc(hidden)] 77 76 pub mod build_assert; 78 77 pub mod clk; 79 78 #[cfg(CONFIG_CONFIGFS_FS)]