2024-07-26 06:13:30 +00:00
|
|
|
use proc_macro::{Span, TokenStream};
|
|
|
|
use quote::{quote, ToTokens};
|
2024-07-26 20:40:07 +00:00
|
|
|
use syn::{FnArg::Typed, Ident, ItemFn, Meta, Pat, PatIdent, PatType, Stmt};
|
2024-07-26 06:13:30 +00:00
|
|
|
|
2024-07-26 20:40:07 +00:00
|
|
|
use crate::Result;
|
2024-07-26 06:13:30 +00:00
|
|
|
|
2024-07-26 20:40:07 +00:00
|
|
|
pub(super) fn refutable(mut item: ItemFn, _args: &[Meta]) -> Result<TokenStream> {
|
2024-07-26 06:13:30 +00:00
|
|
|
let inputs = item.sig.inputs.clone();
|
|
|
|
let stmt = &mut item.block.stmts;
|
|
|
|
let sig = &mut item.sig;
|
|
|
|
for (i, input) in inputs.iter().enumerate() {
|
|
|
|
let Typed(PatType {
|
|
|
|
pat,
|
|
|
|
..
|
|
|
|
}) = input
|
|
|
|
else {
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
|
|
|
|
let Pat::Struct(ref pat) = **pat else {
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
|
|
|
|
let variant = &pat.path;
|
|
|
|
let fields = &pat.fields;
|
|
|
|
|
2024-07-26 20:40:07 +00:00
|
|
|
let Some(Typed(PatType {
|
|
|
|
ref mut pat,
|
|
|
|
..
|
|
|
|
})) = sig.inputs.get_mut(i)
|
|
|
|
else {
|
|
|
|
continue;
|
|
|
|
};
|
|
|
|
|
|
|
|
let name = format!("_args_{i}");
|
|
|
|
*pat = Box::new(Pat::Ident(PatIdent {
|
|
|
|
ident: Ident::new(&name, Span::call_site().into()),
|
|
|
|
attrs: Vec::new(),
|
|
|
|
by_ref: None,
|
|
|
|
mutability: None,
|
|
|
|
subpat: None,
|
|
|
|
}));
|
|
|
|
|
|
|
|
let field = fields.iter();
|
|
|
|
let refute = quote! {
|
|
|
|
let #variant { #( #field ),*, .. } = #name else { panic!("incorrect variant passed to function argument {i}"); };
|
|
|
|
};
|
|
|
|
|
|
|
|
stmt.insert(0, syn::parse2::<Stmt>(refute)?);
|
2024-07-26 06:13:30 +00:00
|
|
|
}
|
|
|
|
|
2024-07-26 20:40:07 +00:00
|
|
|
Ok(item.into_token_stream().into())
|
2024-07-26 06:13:30 +00:00
|
|
|
}
|