Last active
March 25, 2024 08:12
-
-
Save MaxXSoft/7fed1d47268c9a284fd073ddcc6f7a24 to your computer and use it in GitHub Desktop.
Asserting function's return type in Rust.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NOTE: this trick does not work on extern functions (like `extern "C" fn ...`). | |
/// Trait for getting the return type of a function with argument tuple `T`. | |
trait ReturnType<T> { | |
/// The return type. | |
type Output; | |
} | |
/// Helper macro for implementing `ReturnType` for function types. | |
macro_rules! impl_return_type { | |
($($t:ident)*) => { impl_return_type!(@expand $($t)*); }; | |
(@expand) => { impl_return_type!(@impl); }; | |
(@expand $t:ident $($ts:ident)*) => { | |
impl_return_type!(@impl $t $($ts)*); | |
impl_return_type!(@expand $($ts)*); | |
}; | |
(@impl $($t:ident)*) => { | |
impl<Func, Ret $(,$t)*> ReturnType<($($t,)*)> for Func | |
where | |
Func: FnOnce($($t),*) -> Ret, | |
{ | |
type Output = Ret; | |
} | |
} | |
} | |
impl_return_type!(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z); | |
/// Never type (`!`). | |
type Never = <fn() -> ! as ReturnType<()>>::Output; | |
/// Asserts that the return type of the given function is type `R`. | |
/// | |
/// If the return type is not `R`, a compile-time error is generated. | |
macro_rules! assert_return_type { | |
($f:expr, $t:ty) => {{ | |
fn f<F, T, R>(_: F) | |
where | |
F: ReturnType<T, Output = R>, | |
{ | |
} | |
f::<_, _, $t>($f); | |
}}; | |
} | |
// ============================== | |
// Some test code: | |
// ============================== | |
fn test(_: i32) -> Never { | |
panic!() | |
} | |
fn main() { | |
assert_return_type!(test, Never); | |
assert_return_type!(|| { panic!() }, Never); | |
assert_return_type!(main, ()); | |
// Compile error: | |
// assert_return_type!(main, i32); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment