mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	Add the `build_error!` and `build_assert!` macros which leverage
the previously introduced `build_error` crate. Do so in a new
module, called `build_assert`.
The former fails the build if the code path calling it can possibly
be executed. The latter asserts that a boolean expression is `true`
at compile time.
In particular, `build_assert!` can be used in some contexts where
`static_assert!` cannot:
    fn f1<const N: usize>() {
        static_assert!(N > 1);` // Error.
        build_assert!(N > 1);   // Build-time check.
        assert!(N > 1);         // Run-time check.
    }
    #[inline]
    fn f2(n: usize) {
        static_assert!(n > 1);  // Error.
        build_assert!(n > 1);   // Build-time check.
        assert!(n > 1);         // Run-time check.
    }
Signed-off-by: Gary Guo <gary@garyguo.net>
Reviewed-by: Wei Liu <wei.liu@kernel.org>
[Reworded, adapted for upstream and applied latest changes]
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
		
	
			
		
			
				
	
	
		
			82 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			82 lines
		
	
	
	
		
			2.4 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
// SPDX-License-Identifier: GPL-2.0
 | 
						|
 | 
						|
//! Build-time assert.
 | 
						|
 | 
						|
/// Fails the build if the code path calling `build_error!` can possibly be executed.
 | 
						|
///
 | 
						|
/// If the macro is executed in const context, `build_error!` will panic.
 | 
						|
/// If the compiler or optimizer cannot guarantee that `build_error!` can never
 | 
						|
/// be called, a build error will be triggered.
 | 
						|
///
 | 
						|
/// # Examples
 | 
						|
///
 | 
						|
/// ```
 | 
						|
/// # use kernel::build_error;
 | 
						|
/// #[inline]
 | 
						|
/// fn foo(a: usize) -> usize {
 | 
						|
///     a.checked_add(1).unwrap_or_else(|| build_error!("overflow"))
 | 
						|
/// }
 | 
						|
///
 | 
						|
/// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
 | 
						|
/// // foo(usize::MAX); // Fails to compile.
 | 
						|
/// ```
 | 
						|
#[macro_export]
 | 
						|
macro_rules! build_error {
 | 
						|
    () => {{
 | 
						|
        $crate::build_error("")
 | 
						|
    }};
 | 
						|
    ($msg:expr) => {{
 | 
						|
        $crate::build_error($msg)
 | 
						|
    }};
 | 
						|
}
 | 
						|
 | 
						|
/// Asserts that a boolean expression is `true` at compile time.
 | 
						|
///
 | 
						|
/// If the condition is evaluated to `false` in const context, `build_assert!`
 | 
						|
/// will panic. If the compiler or optimizer cannot guarantee the condition will
 | 
						|
/// be evaluated to `true`, a build error will be triggered.
 | 
						|
///
 | 
						|
/// [`static_assert!`] should be preferred to `build_assert!` whenever possible.
 | 
						|
///
 | 
						|
/// # Examples
 | 
						|
///
 | 
						|
/// These examples show that different types of [`assert!`] will trigger errors
 | 
						|
/// at different stage of compilation. It is preferred to err as early as
 | 
						|
/// possible, so [`static_assert!`] should be used whenever possible.
 | 
						|
/// ```ignore
 | 
						|
/// fn foo() {
 | 
						|
///     static_assert!(1 > 1); // Compile-time error
 | 
						|
///     build_assert!(1 > 1); // Build-time error
 | 
						|
///     assert!(1 > 1); // Run-time error
 | 
						|
/// }
 | 
						|
/// ```
 | 
						|
///
 | 
						|
/// When the condition refers to generic parameters or parameters of an inline function,
 | 
						|
/// [`static_assert!`] cannot be used. Use `build_assert!` in this scenario.
 | 
						|
/// ```
 | 
						|
/// fn foo<const N: usize>() {
 | 
						|
///     // `static_assert!(N > 1);` is not allowed
 | 
						|
///     build_assert!(N > 1); // Build-time check
 | 
						|
///     assert!(N > 1); // Run-time check
 | 
						|
/// }
 | 
						|
///
 | 
						|
/// #[inline]
 | 
						|
/// fn bar(n: usize) {
 | 
						|
///     // `static_assert!(n > 1);` is not allowed
 | 
						|
///     build_assert!(n > 1); // Build-time check
 | 
						|
///     assert!(n > 1); // Run-time check
 | 
						|
/// }
 | 
						|
/// ```
 | 
						|
#[macro_export]
 | 
						|
macro_rules! build_assert {
 | 
						|
    ($cond:expr $(,)?) => {{
 | 
						|
        if !$cond {
 | 
						|
            $crate::build_error(concat!("assertion failed: ", stringify!($cond)));
 | 
						|
        }
 | 
						|
    }};
 | 
						|
    ($cond:expr, $msg:expr) => {{
 | 
						|
        if !$cond {
 | 
						|
            $crate::build_error($msg);
 | 
						|
        }
 | 
						|
    }};
 | 
						|
}
 |