Skip to content

Instantly share code, notes, and snippets.

@MaxXSoft
Last active March 25, 2024 08:12
Show Gist options
  • Save MaxXSoft/7fed1d47268c9a284fd073ddcc6f7a24 to your computer and use it in GitHub Desktop.
Save MaxXSoft/7fed1d47268c9a284fd073ddcc6f7a24 to your computer and use it in GitHub Desktop.
Asserting function's return type in Rust.
// 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