add ManuallyDrop for all foreign parameters in extern blocks

This commit is contained in:
vms 2020-09-08 23:09:03 +03:00
parent ff447a3258
commit 00a2a19289
3 changed files with 30 additions and 5 deletions

View File

@ -88,13 +88,15 @@ fn check_field(field: &syn::Field) -> Result<()> {
const DOC_ATTR_NAME: &str = "doc";
// Check that all attributes are doc attributes
if !field.attrs.iter().all(|attr| {
let is_all_attrs_public = field.attrs.iter().all(|attr| {
let meta = match attr.parse_meta() {
Ok(meta) => meta,
Err(_) => return false,
};
meta.path().is_ident(DOC_ATTR_NAME)
}) {
});
if !is_all_attrs_public {
return Err(Error::new(field.span(), "field attributes isn't allowed"));
}

View File

@ -22,6 +22,8 @@ pub(crate) struct WrapperDescriptor {
pub(crate) arg_names: Vec<syn::Ident>,
pub(crate) arg_types: Vec<proc_macro2::TokenStream>,
pub(crate) raw_args: Vec<proc_macro2::TokenStream>,
pub(crate) arg_transforms: proc_macro2::TokenStream,
pub(crate) arg_drops: proc_macro2::TokenStream,
}
pub(crate) struct ExternDescriptor {
@ -34,7 +36,9 @@ pub(crate) struct ExternDescriptor {
/// ```
/// quote! {
/// fn foo(#(#arg_names: #arg_types), *) {
/// let arg_1 = std::mem::ManuallyDrop::new(arg_1);
/// let result = original_foo(#(#raw_args), *);
/// std::mem::ManuallyDrop::drop(&mut arg_1);
/// ...
/// }
/// }
@ -62,11 +66,20 @@ impl ForeignModPrologGlueCodeGenerator for Vec<ParsedType> {
.map(|input_type| input_type.to_token_stream())
.collect();
let arg_names: Vec<syn::Ident> = arg_types
let (arg_names, arg_transforms, arg_drops) = self
.iter()
.enumerate()
.map(|(id, _)| new_ident!(format!("arg_{}", id)))
.collect();
.fold((Vec::new(), proc_macro2::TokenStream::new(), proc_macro2::TokenStream::new()), |(mut arg_names, mut arg_transforms, mut arg_drops), (id, ty)| {
let arg_ident = new_ident!(format!("arg_{}", id));
arg_names.push(arg_ident.clone());
if ty.is_complex_type() {
arg_transforms.extend(quote::quote! { let #arg_ident = std::mem::ManuallyDrop::new(#arg_ident); });
arg_drops.extend(quote::quote! { std::mem::ManuallyDrop::drop(&mut #arg_ident); });
}
(arg_names, arg_transforms, arg_drops)
});
let raw_args: Vec<proc_macro2::TokenStream> = self
.iter()
@ -77,6 +90,8 @@ impl ForeignModPrologGlueCodeGenerator for Vec<ParsedType> {
WrapperDescriptor {
arg_names,
arg_types,
arg_transforms,
arg_drops,
raw_args,
}
}

View File

@ -108,6 +108,8 @@ fn generate_wrapper_functions(extern_item: &fce_ast_types::AstExternModItem) ->
arg_names,
arg_types,
raw_args,
arg_transforms,
arg_drops,
} = signature.input_types.generate_wrapper_prolog();
let FnEpilogDescriptor {
@ -121,9 +123,15 @@ fn generate_wrapper_functions(extern_item: &fce_ast_types::AstExternModItem) ->
#[doc(hidden)]
#[allow(clippy::all)]
#visibility unsafe fn #func_name(#(#arg_names: #arg_types), *) #return_type {
// make complex arguments manually droppable
#arg_transforms
// calling the original function with converted args
#return_expression #import_func_name(#(#raw_args), *);
// drop complex arguments
#arg_drops
// return value conversation from Wasm type to a Rust type
#epilog
}