From 12685c59fca259c6d7b1ff7e4c330a6a00e58688 Mon Sep 17 00:00:00 2001 From: vms Date: Fri, 2 Apr 2021 18:31:19 +0300 Subject: [PATCH] little refactoring --- crates/fce-test-macro/src/lib.rs | 2 +- crates/wit/src/fce_ast_types.rs | 8 ++- crates/wit/src/parse_macro_input/item_fn.rs | 59 +++++++--------- .../src/parse_macro_input/item_foreign_mod.rs | 26 +++---- .../wit/src/parse_macro_input/item_record.rs | 67 ++++++++++--------- crates/wit/src/parsed_type/fn_arg.rs | 5 +- crates/wit/src/parsed_type/fn_epilog.rs | 50 +++++++------- crates/wit/src/parsed_type/fn_prolog.rs | 7 +- .../wit/src/parsed_type/foreign_mod_epilog.rs | 4 +- .../wit/src/parsed_type/foreign_mod_prolog.rs | 12 ++-- .../token_stream_generator/fn_generator.rs | 15 +++-- .../foreign_mod_generator.rs | 23 +++---- .../record_generator/record_serializer.rs | 1 + crates/wit/src/utils.rs | 7 ++ .../export_functions/improper_types.stderr | 2 +- fluence/tests/records/unnamed_structs.rs | 8 +++ fluence/tests/records/unnamed_structs.stderr | 5 ++ fluence/tests/test_runner.rs | 1 + 18 files changed, 164 insertions(+), 138 deletions(-) create mode 100644 fluence/tests/records/unnamed_structs.rs create mode 100644 fluence/tests/records/unnamed_structs.stderr diff --git a/crates/fce-test-macro/src/lib.rs b/crates/fce-test-macro/src/lib.rs index 0e6c594..69ef094 100644 --- a/crates/fce-test-macro/src/lib.rs +++ b/crates/fce-test-macro/src/lib.rs @@ -33,7 +33,7 @@ use proc_macro_error::proc_macro_error; use syn::spanned::Spanned; /// This macro allows user to write tests for services in the following form: -///```ignore +///```rust /// #[fce_test(config = "/path/to/Config.toml", modules_dir = "path/to/service/modules")] /// fn test() { /// let service_result = greeting.greeting("John".to_string()); diff --git a/crates/wit/src/fce_ast_types.rs b/crates/wit/src/fce_ast_types.rs index 6b32376..1454fce 100644 --- a/crates/wit/src/fce_ast_types.rs +++ b/crates/wit/src/fce_ast_types.rs @@ -19,13 +19,19 @@ use crate::parsed_type::ParsedType; use serde::Serialize; use serde::Deserialize; +#[derive(Clone, Serialize, Deserialize)] +pub struct AstFuncArgument { + pub name: String, + pub ty: ParsedType, +} + #[derive(Clone, Serialize, Deserialize)] pub struct AstFunctionSignature { // Option is needed only for skipping serialization/deserialization of syn::ItemFn #[serde(skip)] pub visibility: Option, pub name: String, - pub arguments: Vec<(String, ParsedType)>, + pub arguments: Vec, // fce supports only one return value now, // waiting for adding multi-value support in Wasmer. pub output_type: Option, diff --git a/crates/wit/src/parse_macro_input/item_fn.rs b/crates/wit/src/parse_macro_input/item_fn.rs index 8ed4f28..599beb7 100644 --- a/crates/wit/src/parse_macro_input/item_fn.rs +++ b/crates/wit/src/parse_macro_input/item_fn.rs @@ -16,7 +16,10 @@ use super::ParseMacroInput; use crate::fce_ast_types; -use crate::fce_ast_types::{FCEAst, AstFunctionItem}; +use crate::fce_ast_types::FCEAst; +use crate::fce_ast_types::AstFunctionItem; +use crate::fce_ast_types::AstFuncArgument; +use crate::syn_error; use syn::Result; @@ -45,7 +48,7 @@ pub(super) fn try_to_ast_signature( let arguments = inputs .iter() - .map(|arg| -> Result<(String, ParsedType)> { + .map(|arg| -> Result<_> { let pat = match arg { syn::FnArg::Typed(arg) => arg, _ => { @@ -55,18 +58,21 @@ pub(super) fn try_to_ast_signature( )) } }; - Ok(( - pat.pat - .to_token_stream() - .to_string() - .split(' ') - .last() - .unwrap_or_default() - .to_string(), - ParsedType::from_type(pat.ty.as_ref())?, - )) + + let name = pat + .pat + .to_token_stream() + .to_string() + .split(' ') + .last() + .unwrap_or_default() + .to_string(); + let ty = ParsedType::from_type(pat.ty.as_ref())?; + let ast_arg = AstFuncArgument { name, ty }; + + Ok(ast_arg) }) - .collect::>>()?; + .collect::>>()?; let output_type = ParsedType::from_return_type(&output)?; @@ -81,8 +87,8 @@ pub(super) fn try_to_ast_signature( } /// Check whether the #[fce] macro could be applied to a function. +#[rustfmt::skip] fn check_function(signature: &syn::Signature) -> Result<()> { - use syn::Error; use syn::spanned::Spanned; let syn::Signature { @@ -95,34 +101,19 @@ fn check_function(signature: &syn::Signature) -> Result<()> { } = signature; if let Some(constness) = constness { - return Err(Error::new( - constness.span, - "FCE export function shouldn't be constant", - )); + return syn_error!(constness.span, "FCE export function shouldn't be constant"); } if let Some(unsafety) = unsafety { - return Err(Error::new( - unsafety.span, - "FCE export function shouldn't be unsafe", - )); + return syn_error!(unsafety.span, "FCE export function shouldn't be unsafe"); } if let Some(abi) = abi { - return Err(Error::new( - abi.extern_token.span, - "FCE export function shouldn't have any custom linkage", - )); + return syn_error!(abi.extern_token.span, "FCE export function shouldn't have any custom linkage"); } if generics.where_clause.is_some() { - return Err(Error::new( - signature.span(), - "FCE export function shouldn't use template parameters", - )); + return syn_error!(signature.span(), "FCE export function shouldn't use template parameters"); } if variadic.is_some() { - return Err(Error::new( - variadic.span(), - "FCE export function shouldn't use variadic interface", - )); + return syn_error!(variadic.span(), "FCE export function shouldn't use variadic interface"); } // TODO: check for a lifetime diff --git a/crates/wit/src/parse_macro_input/item_foreign_mod.rs b/crates/wit/src/parse_macro_input/item_foreign_mod.rs index c07b4c5..a1e8190 100644 --- a/crates/wit/src/parse_macro_input/item_foreign_mod.rs +++ b/crates/wit/src/parse_macro_input/item_foreign_mod.rs @@ -17,8 +17,8 @@ use super::ParseMacroInput; use crate::fce_ast_types; use crate::fce_ast_types::FCEAst; +use crate::syn_error; -use syn::Error; use syn::Result; use syn::spanned::Spanned; @@ -30,7 +30,7 @@ impl ParseMacroInput for syn::ItemForeignMod { fn parse_macro_input(self) -> Result { match &self.abi.name { Some(name) if name.value() != "C" => { - return Err(Error::new(self.span(), "only 'C' abi is allowed")) + return syn_error!(self.span(), "only 'C' abi is allowed") } _ => {} }; @@ -69,10 +69,10 @@ impl ParseMacroInput for syn::ItemForeignMod { .collect(); match wasm_import_module { - Some(namespace) if namespace.is_empty() => Err(Error::new( + Some(namespace) if namespace.is_empty() => syn_error!( self_span, - "import module name should be defined by 'wasm_import_module' directive", - )), + "import module name should be defined by 'wasm_import_module' directive" + ), Some(namespace) => { let extern_mod_item = fce_ast_types::AstExternModItem { namespace, @@ -81,10 +81,10 @@ impl ParseMacroInput for syn::ItemForeignMod { }; Ok(FCEAst::ExternMod(extern_mod_item)) } - None => Err(Error::new( + None => syn_error!( self_span, - "import module name should be defined by 'wasm_import_module' directive", - )), + "import module name should be defined by 'wasm_import_module' directive" + ), } } } @@ -93,10 +93,10 @@ fn parse_raw_foreign_item(raw_item: syn::ForeignItem) -> Result function_item, _ => { - return Err(Error::new( + return syn_error!( raw_item.span(), - "#[fce] could be applied only to a function, struct ot extern block", - )) + "#[fce] could be applied only to a function, struct ot extern block" + ) } }; @@ -117,10 +117,10 @@ fn parse_raw_foreign_item(raw_item: syn::ForeignItem) -> Result None, }; - let function = super::item_fn::try_to_ast_signature(function_item.sig, function_item.vis)?; + let signature = super::item_fn::try_to_ast_signature(function_item.sig, function_item.vis)?; let ast_extern_fn_item = fce_ast_types::AstExternFnItem { link_name, - signature: function, + signature, }; Ok(ast_extern_fn_item) diff --git a/crates/wit/src/parse_macro_input/item_record.rs b/crates/wit/src/parse_macro_input/item_record.rs index 9ae3887..d10ce09 100644 --- a/crates/wit/src/parse_macro_input/item_record.rs +++ b/crates/wit/src/parse_macro_input/item_record.rs @@ -15,13 +15,14 @@ */ use super::ParseMacroInput; -use crate::{fce_ast_types, AstRecordField}; +use crate::fce_ast_types; +use crate::AstRecordField; use crate::fce_ast_types::FCEAst; +use crate::syn_error; +use crate::parsed_type::ParsedType; -use syn::Error; use syn::Result; use syn::spanned::Spanned; -use crate::parsed_type::ParsedType; impl ParseMacroInput for syn::ItemStruct { fn parse_macro_input(self) -> Result { @@ -29,29 +30,10 @@ impl ParseMacroInput for syn::ItemStruct { let fields = match &self.fields { syn::Fields::Named(named_fields) => &named_fields.named, - syn::Fields::Unnamed(unnamed_fields) => &unnamed_fields.unnamed, - _ => return Err(Error::new(self.span(), "only named field allowed")), + _ => return syn_error!(self.span(), "only named fields are allowed in structs"), }; - let fields = fields - .iter() - .map(|field| { - check_field(field)?; - let field_name = field.ident.as_ref().map(|ident| { - ident - .to_string() - .split(' ') - .last() - .unwrap_or_default() - .to_string() - }); - let field_type = ParsedType::from_type(&field.ty)?; - Ok(AstRecordField { - name: field_name, - ty: field_type, - }) - }) - .collect::>>()?; + let fields = fields_into_ast(fields)?; let name = self.ident.to_string(); let ast_record_item = fce_ast_types::AstRecordItem { @@ -69,15 +51,38 @@ fn check_record(record: &syn::ItemStruct) -> Result<()> { || record.generics.gt_token.is_some() || record.generics.where_clause.is_some() { - return Err(Error::new( + return syn_error!( record.span(), - "#[fce] couldn't be applied to a struct with generics or lifetimes", - )); + "#[fce] couldn't be applied to a struct with generics or lifetimes" + ); } Ok(()) } +fn fields_into_ast( + fields: &syn::punctuated::Punctuated, +) -> Result> { + fields + .iter() + .map(|field| { + check_field(field)?; + let name = field.ident.as_ref().map(|ident| { + ident + .to_string() + .split(' ') + .last() + .unwrap_or_default() + .to_string() + }); + let ty = ParsedType::from_type(&field.ty)?; + + let record_field = AstRecordField { name, ty }; + Ok(record_field) + }) + .collect::>>() +} + /// Check that record fields satisfy the following requirements: /// - all fields must be public /// - field must have only doc attributes @@ -85,10 +90,10 @@ fn check_field(field: &syn::Field) -> Result<()> { match field.vis { syn::Visibility::Public(_) => {} _ => { - return Err(Error::new( + return syn_error!( field.span(), - "#[fce] could be applied only to struct with all public fields", - )) + "#[fce] could be applied only to struct with all public fields" + ) } }; @@ -104,7 +109,7 @@ fn check_field(field: &syn::Field) -> Result<()> { }); if !is_all_attrs_public { - return Err(Error::new(field.span(), "field attributes isn't allowed")); + return syn_error!(field.span(), "field attributes isn't allowed"); } Ok(()) diff --git a/crates/wit/src/parsed_type/fn_arg.rs b/crates/wit/src/parsed_type/fn_arg.rs index 54edf2a..b37fe64 100644 --- a/crates/wit/src/parsed_type/fn_arg.rs +++ b/crates/wit/src/parsed_type/fn_arg.rs @@ -15,6 +15,7 @@ */ use super::ParsedType; +use crate::fce_ast_types::AstFuncArgument; use crate::wasm_type::RustType; /// This trait could be used to generate raw args needed to construct a export function. @@ -22,9 +23,9 @@ pub(crate) trait FnArgGlueCodeGenerator { fn generate_arguments(&self) -> Vec; } -impl FnArgGlueCodeGenerator for (String, ParsedType) { +impl FnArgGlueCodeGenerator for AstFuncArgument { fn generate_arguments(&self) -> Vec { - match self.1 { + match self.ty { ParsedType::Boolean(_) => vec![RustType::I32], ParsedType::I8(_) => vec![RustType::I8], ParsedType::I16(_) => vec![RustType::I16], diff --git a/crates/wit/src/parsed_type/fn_epilog.rs b/crates/wit/src/parsed_type/fn_epilog.rs index 65404bb..3a16016 100644 --- a/crates/wit/src/parsed_type/fn_epilog.rs +++ b/crates/wit/src/parsed_type/fn_epilog.rs @@ -18,6 +18,7 @@ use super::ParsedType; use super::passing_style_of; use super::PassingStyle; use crate::new_ident; +use crate::fce_ast_types::AstFuncArgument; use quote::quote; @@ -29,6 +30,13 @@ pub(crate) struct FnEpilogDescriptor { pub(crate) mem_forget: proc_macro2::TokenStream, } +/// Contains all ingredients needed for epilog creation. +pub(crate) struct FnEpilogIngredients<'i> { + pub(crate) args: &'i [AstFuncArgument], + pub(crate) converted_args: &'i [syn::Ident], + pub(crate) return_type: &'i Option, +} + /// This trait could be used to generate various parts needed to construct epilog of an export /// function. They are marked with # in the following example: /// ```ignore @@ -44,24 +52,18 @@ pub(crate) trait FnEpilogGlueCodeGenerator { fn generate_fn_epilog(&self) -> FnEpilogDescriptor; } -impl FnEpilogGlueCodeGenerator - for ( - &Vec<(String, ParsedType)>, - &Vec, - &Option, - ) -{ +impl FnEpilogGlueCodeGenerator for FnEpilogIngredients<'_> { fn generate_fn_epilog(&self) -> FnEpilogDescriptor { FnEpilogDescriptor { - fn_return_type: generate_fn_return_type(self.2), - return_expression: generate_return_expression(self.2), - epilog: generate_epilog(self.2), - mem_forget: generate_mem_forget(self.0, self.1, self.2), + fn_return_type: generate_fn_return_type(self.return_type), + return_expression: generate_return_expression(self.return_type), + epilog: generate_epilog(self.return_type), + mem_forget: generate_mem_forgets(self), } } } -fn generate_fn_return_type(ty: &Option) -> proc_macro2::TokenStream { +pub(crate) fn generate_fn_return_type(ty: &Option) -> proc_macro2::TokenStream { let ty = match ty { Some(ParsedType::Boolean(_)) => Some("i32"), Some(ParsedType::I8(_)) => Some("i8"), @@ -90,7 +92,7 @@ fn generate_fn_return_type(ty: &Option) -> proc_macro2::TokenStream } } -fn generate_return_expression(ty: &Option) -> proc_macro2::TokenStream { +pub(crate) fn generate_return_expression(ty: &Option) -> proc_macro2::TokenStream { match ty { None => quote! {}, _ => quote! { @@ -115,10 +117,10 @@ fn generate_epilog(ty: &Option) -> proc_macro2::TokenStream { } } Some(ParsedType::Vector(ty, _)) => { - let generated_serializer_name = String::from("__fce_generated_vec_serializer"); + let generated_serializer_name = "__fce_generated_vec_serializer"; let generated_serializer_ident = new_ident!(generated_serializer_name); let vector_serializer = - super::vector_utils::generate_vector_serializer(ty, &generated_serializer_name); + super::vector_utils::generate_vector_serializer(ty, generated_serializer_name); quote! { #vector_serializer @@ -136,12 +138,8 @@ fn generate_epilog(ty: &Option) -> proc_macro2::TokenStream { /// If an export function returns a reference, this is probably a reference to one /// of the function arguments. If that's the case, reference must be still valid after /// the end of the function. Their deletion will be handled by IT with calling `release_objects`. -fn generate_mem_forget( - args: &Vec<(String, ParsedType)>, - converted_args: &Vec, - ret_type: &Option, -) -> proc_macro2::TokenStream { - let passing_style = ret_type.as_ref().map(passing_style_of); +fn generate_mem_forgets(ingredients: &FnEpilogIngredients<'_>) -> proc_macro2::TokenStream { + let passing_style = ingredients.return_type.as_ref().map(passing_style_of); match passing_style { // result will be deleted by IT side @@ -149,21 +147,21 @@ fn generate_mem_forget( quote! { fluence::internal::add_object_to_release(Box::new(result)); } } Some(PassingStyle::ByRef) | Some(PassingStyle::ByMutRef) => { - mem_forget_by_args(args, converted_args) + mem_forget_by_args(ingredients.args, ingredients.converted_args) } None => quote! {}, } } fn mem_forget_by_args( - args: &Vec<(String, ParsedType)>, - converted_args: &Vec, + args: &[AstFuncArgument], + converted_args: &[syn::Ident], ) -> proc_macro2::TokenStream { debug_assert!(args.len() == converted_args.len()); let mut res = proc_macro2::TokenStream::new(); - for ((_, arg), converted_arg) in args.iter().zip(converted_args) { - let arg_passing_style = passing_style_of(arg); + for (arg, converted_arg) in args.iter().zip(converted_args) { + let arg_passing_style = passing_style_of(&arg.ty); match arg_passing_style { // such values will be deleted inside an export function because they are being moved PassingStyle::ByValue => {} diff --git a/crates/wit/src/parsed_type/fn_prolog.rs b/crates/wit/src/parsed_type/fn_prolog.rs index 6308845..adfb9bb 100644 --- a/crates/wit/src/parsed_type/fn_prolog.rs +++ b/crates/wit/src/parsed_type/fn_prolog.rs @@ -19,6 +19,7 @@ use super::FnArgGlueCodeGenerator; use super::passing_style_of; use crate::new_ident; use crate::wasm_type::RustType; +use crate::fce_ast_types::AstFuncArgument; use crate::parsed_type::PassingStyle; use quote::quote; @@ -47,7 +48,7 @@ pub(crate) trait FnPrologGlueCodeGenerator { fn generate_prolog(&self) -> FnPrologDescriptor; } -impl FnPrologGlueCodeGenerator for Vec<(String, ParsedType)> { +impl FnPrologGlueCodeGenerator for Vec { fn generate_prolog(&self) -> FnPrologDescriptor { let mut raw_arg_names = Vec::with_capacity(self.len()); let mut raw_arg_types = Vec::with_capacity(self.len()); @@ -57,11 +58,11 @@ impl FnPrologGlueCodeGenerator for Vec<(String, ParsedType)> { let mut input_type_id = 0; for arg in self { - let passing_style = passing_style_of(&arg.1); + let passing_style = passing_style_of(&arg.ty); let TypeLifter { converted_arg_ident, type_lifter_glue_code, - } = generate_type_lifting_prolog(&arg.1, passing_style, input_type_id, input_type_id); + } = generate_type_lifting_prolog(&arg.ty, passing_style, input_type_id, input_type_id); let curr_raw_arg_types = arg.generate_arguments(); let arg = quote! { #passing_style #converted_arg_ident }; diff --git a/crates/wit/src/parsed_type/foreign_mod_epilog.rs b/crates/wit/src/parsed_type/foreign_mod_epilog.rs index c221e46..e6e3f93 100644 --- a/crates/wit/src/parsed_type/foreign_mod_epilog.rs +++ b/crates/wit/src/parsed_type/foreign_mod_epilog.rs @@ -57,11 +57,11 @@ impl ForeignModEpilogGlueCodeGenerator for Option { ) }, Some(ParsedType::Vector(ty, _)) => { - let generated_deserializer_name = String::from("__fce_generated_vec_deserializer"); + let generated_deserializer_name = "__fce_generated_vec_deserializer"; let generated_deserializer_ident = new_ident!(generated_deserializer_name); let vector_deserializer = super::vector_utils::generate_vector_deserializer( ty, - &generated_deserializer_name, + generated_deserializer_name, ); quote! { diff --git a/crates/wit/src/parsed_type/foreign_mod_prolog.rs b/crates/wit/src/parsed_type/foreign_mod_prolog.rs index d56f51a..8f2d2aa 100644 --- a/crates/wit/src/parsed_type/foreign_mod_prolog.rs +++ b/crates/wit/src/parsed_type/foreign_mod_prolog.rs @@ -18,6 +18,7 @@ use super::ParsedType; use crate::wasm_type::RustType; use crate::new_ident; use crate::parsed_type::PassingStyle; +use crate::fce_ast_types::AstFuncArgument; pub(crate) struct WrapperDescriptor { pub(crate) arg_names: Vec, @@ -58,32 +59,33 @@ pub(crate) trait ForeignModPrologGlueCodeGenerator { fn generate_extern_prolog(&self) -> ExternDescriptor; } -impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> { +impl ForeignModPrologGlueCodeGenerator for Vec { fn generate_wrapper_prolog(&self) -> WrapperDescriptor { use crate::parsed_type::foreign_mod_arg::ForeignModArgGlueCodeGenerator; use quote::ToTokens; let arg_types: Vec = self .iter() - .map(|(_, input_type)| input_type.to_token_stream()) + .map(|arg| arg.ty.to_token_stream()) .collect(); let (arg_names, arg_transforms, arg_drops) = self .iter() .enumerate() - .fold((Vec::new(), proc_macro2::TokenStream::new(), proc_macro2::TokenStream::new()), |(mut arg_names, mut arg_transforms, mut arg_drops), (id, (_, ty))| { + .fold((Vec::new(), proc_macro2::TokenStream::new(), proc_macro2::TokenStream::new()), |(mut arg_names, mut arg_transforms, mut arg_drops), (id, arg)| { let arg_name = format!("arg_{}", id); let arg_ident = new_ident!(arg_name); arg_names.push(arg_ident.clone()); // arguments of following two types shouldn't be deleted after transformation to raw view - match ty { + match &arg.ty { ParsedType::Utf8String(PassingStyle::ByValue) => { arg_transforms.extend(quote::quote! { let mut #arg_ident = std::mem::ManuallyDrop::new(#arg_ident); }); arg_drops.extend(quote::quote! { std::mem::ManuallyDrop::drop(&mut #arg_ident); }); }, ParsedType::Vector(ty, _) => { let generated_serializer_name = format!("__fce_generated_vec_serializer_{}", arg_name); + let generated_serializer_ident = new_ident!(generated_serializer_name); let vector_serializer = super::vector_utils::generate_vector_serializer(ty, &generated_serializer_name); @@ -104,7 +106,7 @@ impl ForeignModPrologGlueCodeGenerator for Vec<(String, ParsedType)> { let raw_args: Vec = self .iter() .enumerate() - .map(|(id, (_, input_type))| input_type.generate_raw_args(id)) + .map(|(id, arg)| arg.ty.generate_raw_args(id)) .collect(); WrapperDescriptor { diff --git a/crates/wit/src/token_stream_generator/fn_generator.rs b/crates/wit/src/token_stream_generator/fn_generator.rs index ec0c161..b22d64c 100644 --- a/crates/wit/src/token_stream_generator/fn_generator.rs +++ b/crates/wit/src/token_stream_generator/fn_generator.rs @@ -17,8 +17,10 @@ use crate::fce_ast_types; use crate::parsed_type::FnEpilogGlueCodeGenerator; use crate::parsed_type::FnEpilogDescriptor; +use crate::parsed_type::FnEpilogIngredients; use crate::parsed_type::FnPrologGlueCodeGenerator; use crate::parsed_type::FnPrologDescriptor; + use crate::new_ident; use proc_macro2::TokenStream; @@ -52,17 +54,18 @@ impl quote::ToTokens for fce_ast_types::AstFunctionItem { args, } = &signature.arguments.generate_prolog(); + let epilog_ingredients = FnEpilogIngredients { + args: &signature.arguments, + converted_args: converted_arg_idents, + return_type: &signature.output_type, + }; + let FnEpilogDescriptor { fn_return_type, return_expression, epilog, mem_forget, - } = ( - &signature.arguments, - converted_arg_idents, - &signature.output_type, - ) - .generate_fn_epilog(); + } = epilog_ingredients.generate_fn_epilog(); // here this Option must be Some let original_func = &self.original; diff --git a/crates/wit/src/token_stream_generator/foreign_mod_generator.rs b/crates/wit/src/token_stream_generator/foreign_mod_generator.rs index 131cdb2..4f5f678 100644 --- a/crates/wit/src/token_stream_generator/foreign_mod_generator.rs +++ b/crates/wit/src/token_stream_generator/foreign_mod_generator.rs @@ -42,7 +42,7 @@ impl quote::ToTokens for fce_ast_types::AstExternModItem { #[link(wasm_import_module = #wasm_import_module_name)] #[cfg(target_arch = "wasm32")] extern "C" { - #generated_imports + #(#generated_imports)* } #[cfg(not(target_arch = "wasm32"))] @@ -61,15 +61,14 @@ impl quote::ToTokens for fce_ast_types::AstExternModItem { } } -fn generate_extern_section_items(extern_item: &fce_ast_types::AstExternModItem) -> TokenStream { - let mut token_stream = TokenStream::new(); +fn generate_extern_section_items( + extern_item: &fce_ast_types::AstExternModItem, +) -> Vec { + let mut section_items = Vec::with_capacity(extern_item.imports.len()); for import in &extern_item.imports { let signature = &import.signature; - - let FnEpilogDescriptor { fn_return_type, .. } = - (&vec![], &vec![], &signature.output_type).generate_fn_epilog(); - + let fn_return_type = crate::parsed_type::generate_fn_return_type(&signature.output_type); let link_name = import.link_name.as_ref().unwrap_or(&signature.name); let import_name = generate_import_name(&signature.name); let ExternDescriptor { @@ -82,10 +81,10 @@ fn generate_extern_section_items(extern_item: &fce_ast_types::AstExternModItem) fn #import_name(#(#raw_arg_names: #raw_arg_types),*) #fn_return_type; }; - token_stream.extend(func); + section_items.push(func); } - token_stream + section_items } #[rustfmt::skip] @@ -113,10 +112,8 @@ fn generate_wrapper_functions(extern_item: &fce_ast_types::AstExternModItem) -> arg_drops, } = signature.arguments.generate_wrapper_prolog(); - let FnEpilogDescriptor { - return_expression, .. - } = (&vec![], &vec![], &signature.output_type).generate_fn_epilog(); - + let return_expression = + crate::parsed_type::generate_return_expression(&signature.output_type); let epilog = signature.output_type.generate_wrapper_epilog(); let wrapper_func = quote! { diff --git a/crates/wit/src/token_stream_generator/record_generator/record_serializer.rs b/crates/wit/src/token_stream_generator/record_generator/record_serializer.rs index ba6e3ac..8556e94 100644 --- a/crates/wit/src/token_stream_generator/record_generator/record_serializer.rs +++ b/crates/wit/src/token_stream_generator/record_generator/record_serializer.rs @@ -50,6 +50,7 @@ impl RecordSerializerGlueCodeGenerator for fce_ast_types::AstRecordItem { field.name.as_ref().unwrap(), id ); + let generated_serializer_ident = new_ident!(generated_serializer_name); let vector_serializer = crate::parsed_type::generate_vector_serializer( ty, diff --git a/crates/wit/src/utils.rs b/crates/wit/src/utils.rs index 13f9f10..0d7a862 100644 --- a/crates/wit/src/utils.rs +++ b/crates/wit/src/utils.rs @@ -44,6 +44,13 @@ macro_rules! prepare_global_data { }; } +#[macro_export] +macro_rules! syn_error { + ($span:expr, $message:expr) => { + Err(syn::Error::new($span, $message)) + }; +} + /// Calculate record size in an internal serialized view. pub fn get_record_size<'a>( fields: impl Iterator, diff --git a/fluence/tests/export_functions/improper_types.stderr b/fluence/tests/export_functions/improper_types.stderr index 484a611..757423b 100644 --- a/fluence/tests/export_functions/improper_types.stderr +++ b/fluence/tests/export_functions/improper_types.stderr @@ -16,7 +16,7 @@ error: types with lifetimes or generics aren't allowed 14 | fn test3(_arg_1: std::collections::HashMap) {} | ^^^^^^^^^^^^^^^^^^^^ -error: Incorrect argument type - passing only by value is supported now +error: Incorrect argument type, only path or reference are available on this position --> $DIR/improper_types.rs:17:26 | 17 | fn test4(_arg_1: i32) -> (i32, i32) { diff --git a/fluence/tests/records/unnamed_structs.rs b/fluence/tests/records/unnamed_structs.rs new file mode 100644 index 0000000..593069d --- /dev/null +++ b/fluence/tests/records/unnamed_structs.rs @@ -0,0 +1,8 @@ +#![allow(improper_ctypes)] + +use fluence::fce; + +fn main() {} + +#[fce] +struct A(pub i32, pub u32); diff --git a/fluence/tests/records/unnamed_structs.stderr b/fluence/tests/records/unnamed_structs.stderr new file mode 100644 index 0000000..c219748 --- /dev/null +++ b/fluence/tests/records/unnamed_structs.stderr @@ -0,0 +1,5 @@ +error: only named fields are allowed in structs + --> $DIR/unnamed_structs.rs:8:1 + | +8 | struct A(pub i32, pub u32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/fluence/tests/test_runner.rs b/fluence/tests/test_runner.rs index ff32c6d..38b8782 100644 --- a/fluence/tests/test_runner.rs +++ b/fluence/tests/test_runner.rs @@ -13,4 +13,5 @@ fn test() { tests.pass("tests/records/empty_struct.rs"); tests.compile_fail("tests/records/struct_with_improper_types.rs"); tests.compile_fail("tests/records/struct_with_private_fields.rs"); + tests.compile_fail("tests/records/unnamed_structs.rs"); }