From 235ad66d2b3d9731d2f79e11f75cb797083f5de6 Mon Sep 17 00:00:00 2001 From: Stephen Chung Date: Tue, 22 Sep 2020 22:19:21 +0800 Subject: [PATCH] Flatten types in functions. --- codegen/src/function.rs | 63 +++++++++++++++++++------------------- codegen/src/rhai_module.rs | 24 +++++++-------- 2 files changed, 43 insertions(+), 44 deletions(-) diff --git a/codegen/src/function.rs b/codegen/src/function.rs index 2fca6d96..fde1b6a3 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -16,6 +16,7 @@ use quote::{quote, quote_spanned}; use syn::{parse::Parse, parse::ParseStream, parse::Parser, spanned::Spanned}; use crate::attrs::{ExportInfo, ExportScope, ExportedParams}; +use crate::rhai_module::flatten_type_groups; #[derive(Clone, Debug, Eq, PartialEq)] pub enum Index { @@ -223,27 +224,29 @@ impl Parse for ExportedFn { syn::FnArg::Receiver(syn::Receiver { reference: Some(_), .. }) => true, - syn::FnArg::Typed(syn::PatType { ref ty, .. }) => match ty.as_ref() { - &syn::Type::Reference(syn::TypeReference { - mutability: Some(_), - .. - }) => true, - &syn::Type::Reference(syn::TypeReference { - mutability: None, - ref elem, - .. - }) => match elem.as_ref() { - &syn::Type::Path(ref p) if p.path == str_type_path => false, - _ => { - return Err(syn::Error::new( - ty.span(), - "references from Rhai in this position \ + syn::FnArg::Typed(syn::PatType { ref ty, .. }) => { + match flatten_type_groups(ty.as_ref()) { + &syn::Type::Reference(syn::TypeReference { + mutability: Some(_), + .. + }) => true, + &syn::Type::Reference(syn::TypeReference { + mutability: None, + ref elem, + .. + }) => match flatten_type_groups(elem.as_ref()) { + &syn::Type::Path(ref p) if p.path == str_type_path => false, + _ => { + return Err(syn::Error::new( + ty.span(), + "references from Rhai in this position \ must be mutable", - )) - } - }, - _ => false, - }, + )) + } + }, + _ => false, + } + } _ => false, } } else { @@ -257,7 +260,7 @@ impl Parse for ExportedFn { syn::FnArg::Typed(syn::PatType { ref ty, .. }) => ty, _ => panic!("internal error: receiver argument outside of first position!?"), }; - let is_ok = match ty.as_ref() { + let is_ok = match flatten_type_groups(ty.as_ref()) { &syn::Type::Reference(syn::TypeReference { mutability: Some(_), .. @@ -266,7 +269,9 @@ impl Parse for ExportedFn { mutability: None, ref elem, .. - }) => matches!(elem.as_ref(), &syn::Type::Path(ref p) if p.path == str_type_path), + }) => { + matches!(flatten_type_groups(elem.as_ref()), &syn::Type::Path(ref p) if p.path == str_type_path) + } &syn::Type::Verbatim(_) => false, _ => true, }; @@ -605,13 +610,9 @@ impl ExportedFn { let var = syn::Ident::new("arg0", proc_macro2::Span::call_site()); match first_arg { syn::FnArg::Typed(pattern) => { - let arg_type: &syn::Type = { - match pattern.ty.as_ref() { - &syn::Type::Reference(syn::TypeReference { ref elem, .. }) => { - elem.as_ref() - } - ref p => p, - } + let arg_type: &syn::Type = match flatten_type_groups(pattern.ty.as_ref()) { + &syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(), + p => p, }; let downcast_span = quote_spanned!( arg_type.span()=> &mut args[0usize].write_lock::<#arg_type>().unwrap()); @@ -648,12 +649,12 @@ impl ExportedFn { match arg { syn::FnArg::Typed(pattern) => { let arg_type: &syn::Type = pattern.ty.as_ref(); - let downcast_span = match pattern.ty.as_ref() { + let downcast_span = match flatten_type_groups(pattern.ty.as_ref()) { &syn::Type::Reference(syn::TypeReference { mutability: None, ref elem, .. - }) => match elem.as_ref() { + }) => match flatten_type_groups(elem.as_ref()) { &syn::Type::Path(ref p) if p.path == str_type_path => { is_string = true; is_ref = true; diff --git a/codegen/src/rhai_module.rs b/codegen/src/rhai_module.rs index 2ebfb930..b65d891b 100644 --- a/codegen/src/rhai_module.rs +++ b/codegen/src/rhai_module.rs @@ -85,22 +85,12 @@ pub(crate) fn generate_body( .map(|fnarg| match fnarg { syn::FnArg::Receiver(_) => panic!("internal error: receiver fn outside impl!?"), syn::FnArg::Typed(syn::PatType { ref ty, .. }) => { - fn flatten_groups(ty: &syn::Type) -> &syn::Type { - match ty { - syn::Type::Group(syn::TypeGroup { ref elem, .. }) - | syn::Type::Paren(syn::TypeParen { ref elem, .. }) => { - flatten_groups(elem.as_ref()) - } - _ => ty, - } - } - - let arg_type = match flatten_groups(ty.as_ref()) { + let arg_type = match flatten_type_groups(ty.as_ref()) { syn::Type::Reference(syn::TypeReference { mutability: None, ref elem, .. - }) => match flatten_groups(elem.as_ref()) { + }) => match flatten_type_groups(elem.as_ref()) { syn::Type::Path(ref p) if p.path == str_type_path => { syn::parse2::(quote! { ImmutableString }) @@ -117,7 +107,7 @@ pub(crate) fn generate_body( mutability: Some(_), ref elem, .. - }) => match flatten_groups(elem.as_ref()) { + }) => match flatten_type_groups(elem.as_ref()) { syn::Type::Path(ref p) => syn::parse2::(quote! { #p }) .unwrap(), @@ -184,6 +174,14 @@ pub(crate) fn generate_body( } } +pub(crate) fn flatten_type_groups(ty: &syn::Type) -> &syn::Type { + match ty { + syn::Type::Group(syn::TypeGroup { ref elem, .. }) + | syn::Type::Paren(syn::TypeParen { ref elem, .. }) => flatten_type_groups(elem.as_ref()), + _ => ty, + } +} + pub(crate) fn check_rename_collisions(fns: &Vec) -> Result<(), syn::Error> { let mut renames = HashMap::::new(); let mut names = HashMap::::new();