Flatten types in functions.

This commit is contained in:
Stephen Chung 2020-09-22 22:19:21 +08:00
parent 5a37497a22
commit 235ad66d2b
2 changed files with 43 additions and 44 deletions

View File

@ -16,6 +16,7 @@ use quote::{quote, quote_spanned};
use syn::{parse::Parse, parse::ParseStream, parse::Parser, spanned::Spanned}; use syn::{parse::Parse, parse::ParseStream, parse::Parser, spanned::Spanned};
use crate::attrs::{ExportInfo, ExportScope, ExportedParams}; use crate::attrs::{ExportInfo, ExportScope, ExportedParams};
use crate::rhai_module::flatten_type_groups;
#[derive(Clone, Debug, Eq, PartialEq)] #[derive(Clone, Debug, Eq, PartialEq)]
pub enum Index { pub enum Index {
@ -223,27 +224,29 @@ impl Parse for ExportedFn {
syn::FnArg::Receiver(syn::Receiver { syn::FnArg::Receiver(syn::Receiver {
reference: Some(_), .. reference: Some(_), ..
}) => true, }) => true,
syn::FnArg::Typed(syn::PatType { ref ty, .. }) => match ty.as_ref() { syn::FnArg::Typed(syn::PatType { ref ty, .. }) => {
&syn::Type::Reference(syn::TypeReference { match flatten_type_groups(ty.as_ref()) {
mutability: Some(_), &syn::Type::Reference(syn::TypeReference {
.. mutability: Some(_),
}) => true, ..
&syn::Type::Reference(syn::TypeReference { }) => true,
mutability: None, &syn::Type::Reference(syn::TypeReference {
ref elem, mutability: None,
.. ref elem,
}) => match elem.as_ref() { ..
&syn::Type::Path(ref p) if p.path == str_type_path => false, }) => 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(), return Err(syn::Error::new(
"references from Rhai in this position \ ty.span(),
"references from Rhai in this position \
must be mutable", must be mutable",
)) ))
} }
}, },
_ => false, _ => false,
}, }
}
_ => false, _ => false,
} }
} else { } else {
@ -257,7 +260,7 @@ impl Parse for ExportedFn {
syn::FnArg::Typed(syn::PatType { ref ty, .. }) => ty, syn::FnArg::Typed(syn::PatType { ref ty, .. }) => ty,
_ => panic!("internal error: receiver argument outside of first position!?"), _ => 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 { &syn::Type::Reference(syn::TypeReference {
mutability: Some(_), mutability: Some(_),
.. ..
@ -266,7 +269,9 @@ impl Parse for ExportedFn {
mutability: None, mutability: None,
ref elem, 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, &syn::Type::Verbatim(_) => false,
_ => true, _ => true,
}; };
@ -605,13 +610,9 @@ impl ExportedFn {
let var = syn::Ident::new("arg0", proc_macro2::Span::call_site()); let var = syn::Ident::new("arg0", proc_macro2::Span::call_site());
match first_arg { match first_arg {
syn::FnArg::Typed(pattern) => { syn::FnArg::Typed(pattern) => {
let arg_type: &syn::Type = { let arg_type: &syn::Type = match flatten_type_groups(pattern.ty.as_ref()) {
match pattern.ty.as_ref() { &syn::Type::Reference(syn::TypeReference { ref elem, .. }) => elem.as_ref(),
&syn::Type::Reference(syn::TypeReference { ref elem, .. }) => { p => p,
elem.as_ref()
}
ref p => p,
}
}; };
let downcast_span = quote_spanned!( let downcast_span = quote_spanned!(
arg_type.span()=> &mut args[0usize].write_lock::<#arg_type>().unwrap()); arg_type.span()=> &mut args[0usize].write_lock::<#arg_type>().unwrap());
@ -648,12 +649,12 @@ impl ExportedFn {
match arg { match arg {
syn::FnArg::Typed(pattern) => { syn::FnArg::Typed(pattern) => {
let arg_type: &syn::Type = pattern.ty.as_ref(); 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 { &syn::Type::Reference(syn::TypeReference {
mutability: None, mutability: None,
ref elem, ref elem,
.. ..
}) => match elem.as_ref() { }) => match flatten_type_groups(elem.as_ref()) {
&syn::Type::Path(ref p) if p.path == str_type_path => { &syn::Type::Path(ref p) if p.path == str_type_path => {
is_string = true; is_string = true;
is_ref = true; is_ref = true;

View File

@ -85,22 +85,12 @@ pub(crate) fn generate_body(
.map(|fnarg| match fnarg { .map(|fnarg| match fnarg {
syn::FnArg::Receiver(_) => panic!("internal error: receiver fn outside impl!?"), syn::FnArg::Receiver(_) => panic!("internal error: receiver fn outside impl!?"),
syn::FnArg::Typed(syn::PatType { ref ty, .. }) => { syn::FnArg::Typed(syn::PatType { ref ty, .. }) => {
fn flatten_groups(ty: &syn::Type) -> &syn::Type { let arg_type = match flatten_type_groups(ty.as_ref()) {
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()) {
syn::Type::Reference(syn::TypeReference { syn::Type::Reference(syn::TypeReference {
mutability: None, mutability: None,
ref elem, 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::Type::Path(ref p) if p.path == str_type_path => {
syn::parse2::<syn::Type>(quote! { syn::parse2::<syn::Type>(quote! {
ImmutableString }) ImmutableString })
@ -117,7 +107,7 @@ pub(crate) fn generate_body(
mutability: Some(_), mutability: Some(_),
ref elem, ref elem,
.. ..
}) => match flatten_groups(elem.as_ref()) { }) => match flatten_type_groups(elem.as_ref()) {
syn::Type::Path(ref p) => syn::parse2::<syn::Type>(quote! { syn::Type::Path(ref p) => syn::parse2::<syn::Type>(quote! {
#p }) #p })
.unwrap(), .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<ExportedFn>) -> Result<(), syn::Error> { pub(crate) fn check_rename_collisions(fns: &Vec<ExportedFn>) -> Result<(), syn::Error> {
let mut renames = HashMap::<String, proc_macro2::Span>::new(); let mut renames = HashMap::<String, proc_macro2::Span>::new();
let mut names = HashMap::<String, proc_macro2::Span>::new(); let mut names = HashMap::<String, proc_macro2::Span>::new();