Merge pull request #364 from schungx/master

Refine codegen errors.
This commit is contained in:
Stephen Chung 2021-02-27 12:29:37 +08:00 committed by GitHub
commit 0c62a620ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 70 additions and 50 deletions

View File

@ -1,6 +1,8 @@
Rhai Release Notes Rhai Release Notes
================== ==================
This version introduces functions with `Dynamic` parameters acting as wildcards.
Version 0.19.13 Version 0.19.13
=============== ===============

View File

@ -98,8 +98,8 @@ pub fn print_type(ty: &syn::Type) -> String {
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct ExportedFnParams { pub struct ExportedFnParams {
pub name: Vec<String>, pub name: Vec<String>,
pub return_raw: bool, pub return_raw: Option<proc_macro2::Span>,
pub pure: bool, pub pure: Option<proc_macro2::Span>,
pub skip: bool, pub skip: bool,
pub special: FnSpecialAccess, pub special: FnSpecialAccess,
pub namespace: FnNamespaceAccess, pub namespace: FnNamespaceAccess,
@ -137,8 +137,8 @@ impl ExportedParams for ExportedFnParams {
items: attrs, items: attrs,
} = info; } = info;
let mut name = Vec::new(); let mut name = Vec::new();
let mut return_raw = false; let mut return_raw = None;
let mut pure = false; let mut pure = None;
let mut skip = false; let mut skip = false;
let mut namespace = FnNamespaceAccess::Unset; let mut namespace = FnNamespaceAccess::Unset;
let mut special = FnSpecialAccess::None; let mut special = FnSpecialAccess::None;
@ -194,18 +194,28 @@ impl ExportedParams for ExportedFnParams {
return Err(syn::Error::new(s.span(), "extraneous value")) return Err(syn::Error::new(s.span(), "extraneous value"))
} }
("pure", None) => pure = true, ("pure", None) => pure = Some(item_span),
("return_raw", None) => return_raw = true, ("return_raw", None) => return_raw = Some(item_span),
("skip", None) => skip = true, ("skip", None) => skip = true,
("global", None) => match namespace { ("global", None) => match namespace {
FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Global, FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Global,
FnNamespaceAccess::Global => (), FnNamespaceAccess::Global => (),
_ => return Err(syn::Error::new(key.span(), "conflicting namespace")), FnNamespaceAccess::Internal => {
return Err(syn::Error::new(
key.span(),
"namespace is already set to 'internal'",
))
}
}, },
("internal", None) => match namespace { ("internal", None) => match namespace {
FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Internal, FnNamespaceAccess::Unset => namespace = FnNamespaceAccess::Internal,
FnNamespaceAccess::Internal => (), FnNamespaceAccess::Internal => (),
_ => return Err(syn::Error::new(key.span(), "conflicting namespace")), FnNamespaceAccess::Global => {
return Err(syn::Error::new(
key.span(),
"namespace is already set to 'global'",
))
}
}, },
("get", Some(s)) => { ("get", Some(s)) => {
@ -478,10 +488,10 @@ impl ExportedFn {
} }
pub fn exported_name<'n>(&'n self) -> Cow<'n, str> { pub fn exported_name<'n>(&'n self) -> Cow<'n, str> {
self.params.name.last().map_or_else( self.params
|| self.signature.ident.to_string().into(), .name
|s| s.as_str().into(), .last()
) .map_or_else(|| self.signature.ident.to_string().into(), |s| s.into())
} }
pub fn arg_list(&self) -> impl Iterator<Item = &syn::FnArg> { pub fn arg_list(&self) -> impl Iterator<Item = &syn::FnArg> {
@ -503,23 +513,31 @@ impl ExportedFn {
} }
pub fn set_params(&mut self, mut params: ExportedFnParams) -> syn::Result<()> { pub fn set_params(&mut self, mut params: ExportedFnParams) -> syn::Result<()> {
// Several issues are checked here to avoid issues with diagnostics caused by raising them // Several issues are checked here to avoid issues with diagnostics caused by raising them later.
// later.
// //
// 1. Do not allow non-returning raw functions. // 1a. Do not allow non-returning raw functions.
// //
if params.return_raw && self.return_type().is_none() { if params.return_raw.is_some() && self.return_type().is_none() {
return Err(syn::Error::new( return Err(syn::Error::new(
self.signature.span(), params.return_raw.unwrap(),
"functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>>", "functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>>",
)); ));
} }
// 1b. Do not allow non-method pure functions.
//
if params.pure.is_some() && !self.mutable_receiver() {
return Err(syn::Error::new(
params.pure.unwrap(),
"'pure' is not necessary on functions without a &mut first parameter",
));
}
match params.special { match params.special {
// 2a. Property getters must take only the subject as an argument. // 2a. Property getters must take only the subject as an argument.
FnSpecialAccess::Property(Property::Get(_)) if self.arg_count() != 1 => { FnSpecialAccess::Property(Property::Get(_)) if self.arg_count() != 1 => {
return Err(syn::Error::new( return Err(syn::Error::new(
self.signature.span(), self.signature.inputs.span(),
"property getter requires exactly 1 parameter", "property getter requires exactly 1 parameter",
)) ))
} }
@ -533,21 +551,21 @@ impl ExportedFn {
// 3a. Property setters must take the subject and a new value as arguments. // 3a. Property setters must take the subject and a new value as arguments.
FnSpecialAccess::Property(Property::Set(_)) if self.arg_count() != 2 => { FnSpecialAccess::Property(Property::Set(_)) if self.arg_count() != 2 => {
return Err(syn::Error::new( return Err(syn::Error::new(
self.signature.span(), self.signature.inputs.span(),
"property setter requires exactly 2 parameters", "property setter requires exactly 2 parameters",
)) ))
} }
// 3b. Property setters must return nothing. // 3b. Property setters must return nothing.
FnSpecialAccess::Property(Property::Set(_)) if self.return_type().is_some() => { FnSpecialAccess::Property(Property::Set(_)) if self.return_type().is_some() => {
return Err(syn::Error::new( return Err(syn::Error::new(
self.signature.span(), self.signature.output.span(),
"property setter cannot return any value", "property setter cannot return any value",
)) ))
} }
// 4a. Index getters must take the subject and the accessed "index" as arguments. // 4a. Index getters must take the subject and the accessed "index" as arguments.
FnSpecialAccess::Index(Index::Get) if self.arg_count() != 2 => { FnSpecialAccess::Index(Index::Get) if self.arg_count() != 2 => {
return Err(syn::Error::new( return Err(syn::Error::new(
self.signature.span(), self.signature.inputs.span(),
"index getter requires exactly 2 parameters", "index getter requires exactly 2 parameters",
)) ))
} }
@ -561,15 +579,15 @@ impl ExportedFn {
// 5a. Index setters must take the subject, "index", and new value as arguments. // 5a. Index setters must take the subject, "index", and new value as arguments.
FnSpecialAccess::Index(Index::Set) if self.arg_count() != 3 => { FnSpecialAccess::Index(Index::Set) if self.arg_count() != 3 => {
return Err(syn::Error::new( return Err(syn::Error::new(
self.signature.span(), self.signature.inputs.span(),
"index setter requires exactly 3 parameters", "index setter requires exactly 3 parameters",
)) ))
} }
// 5b. Index setters must return nothing. // 5b. Index setters must return nothing.
FnSpecialAccess::Index(Index::Set) if self.return_type().is_some() => { FnSpecialAccess::Index(Index::Set) if self.return_type().is_some() => {
return Err(syn::Error::new( return Err(syn::Error::new(
self.signature.span(), self.signature.output.span(),
"index setter cannot return a value", "index setter cannot return any value",
)) ))
} }
_ => {} _ => {}
@ -635,7 +653,7 @@ impl ExportedFn {
.return_type() .return_type()
.map(|r| r.span()) .map(|r| r.span())
.unwrap_or_else(|| proc_macro2::Span::call_site()); .unwrap_or_else(|| proc_macro2::Span::call_site());
if self.params.return_raw { if self.params.return_raw.is_some() {
quote_spanned! { return_span => quote_spanned! { return_span =>
pub #dynamic_signature { pub #dynamic_signature {
#name(#(#arguments),*) #name(#(#arguments),*)
@ -659,7 +677,7 @@ impl ExportedFn {
pub fn generate_callable(&self, on_type_name: &str) -> proc_macro2::TokenStream { pub fn generate_callable(&self, on_type_name: &str) -> proc_macro2::TokenStream {
let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span()); let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span());
let callable_fn_name: syn::Ident = syn::Ident::new( let callable_fn_name: syn::Ident = syn::Ident::new(
format!("{}_callable", on_type_name.to_lowercase()).as_str(), &format!("{}_callable", on_type_name.to_lowercase()),
self.name().span(), self.name().span(),
); );
quote! { quote! {
@ -672,7 +690,7 @@ impl ExportedFn {
pub fn generate_input_names(&self, on_type_name: &str) -> proc_macro2::TokenStream { pub fn generate_input_names(&self, on_type_name: &str) -> proc_macro2::TokenStream {
let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span()); let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span());
let input_names_fn_name: syn::Ident = syn::Ident::new( let input_names_fn_name: syn::Ident = syn::Ident::new(
format!("{}_input_names", on_type_name.to_lowercase()).as_str(), &format!("{}_input_names", on_type_name.to_lowercase()),
self.name().span(), self.name().span(),
); );
quote! { quote! {
@ -685,7 +703,7 @@ impl ExportedFn {
pub fn generate_input_types(&self, on_type_name: &str) -> proc_macro2::TokenStream { pub fn generate_input_types(&self, on_type_name: &str) -> proc_macro2::TokenStream {
let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span()); let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span());
let input_types_fn_name: syn::Ident = syn::Ident::new( let input_types_fn_name: syn::Ident = syn::Ident::new(
format!("{}_input_types", on_type_name.to_lowercase()).as_str(), &format!("{}_input_types", on_type_name.to_lowercase()),
self.name().span(), self.name().span(),
); );
quote! { quote! {
@ -698,7 +716,7 @@ impl ExportedFn {
pub fn generate_return_type(&self, on_type_name: &str) -> proc_macro2::TokenStream { pub fn generate_return_type(&self, on_type_name: &str) -> proc_macro2::TokenStream {
let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span()); let token_name: syn::Ident = syn::Ident::new(on_type_name, self.name().span());
let return_type_fn_name: syn::Ident = syn::Ident::new( let return_type_fn_name: syn::Ident = syn::Ident::new(
format!("{}_return_type", on_type_name.to_lowercase()).as_str(), &format!("{}_return_type", on_type_name.to_lowercase()),
self.name().span(), self.name().span(),
); );
quote! { quote! {
@ -750,7 +768,7 @@ impl ExportedFn {
}) })
.unwrap(), .unwrap(),
); );
if !self.params().pure { if !self.params().pure.is_some() {
let arg_lit_str = let arg_lit_str =
syn::LitStr::new(&pat.to_token_stream().to_string(), pat.span()); syn::LitStr::new(&pat.to_token_stream().to_string(), pat.span());
unpack_statements.push( unpack_statements.push(
@ -871,7 +889,7 @@ impl ExportedFn {
.return_type() .return_type()
.map(|r| r.span()) .map(|r| r.span())
.unwrap_or_else(|| proc_macro2::Span::call_site()); .unwrap_or_else(|| proc_macro2::Span::call_site());
let return_expr = if !self.params.return_raw { let return_expr = if !self.params.return_raw.is_some() {
if self.return_dynamic { if self.return_dynamic {
quote_spanned! { return_span => quote_spanned! { return_span =>
Ok(#sig_name(#(#unpack_exprs),*)) Ok(#sig_name(#(#unpack_exprs),*))

View File

@ -217,7 +217,7 @@ impl Module {
pub fn exported_name(&self) -> Cow<str> { pub fn exported_name(&self) -> Cow<str> {
if !self.params.name.is_empty() { if !self.params.name.is_empty() {
self.params.name.as_str().into() (&self.params.name).into()
} else { } else {
self.module_name().to_string().into() self.module_name().to_string().into()
} }

View File

@ -1,8 +1,8 @@
error: functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>> error: functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>>
--> $DIR/export_fn_raw_noreturn.rs:10:5 --> $DIR/export_fn_raw_noreturn.rs:9:13
| |
10 | pub fn test_fn(input: &mut Point) { 9 | #[export_fn(return_raw)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_raw_noreturn.rs:19:5 --> $DIR/export_fn_raw_noreturn.rs:19:5

View File

@ -1,8 +1,8 @@
error: functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>> error: functions marked with 'return_raw' must return Result<Dynamic, Box<EvalAltResult>>
--> $DIR/export_mod_raw_noreturn.rs:12:5 --> $DIR/export_mod_raw_noreturn.rs:11:11
| |
12 | pub fn test_fn(input: &mut Point) { 11 | #[rhai_fn(return_raw)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared crate or module `test_mod` error[E0433]: failed to resolve: use of undeclared crate or module `test_mod`
--> $DIR/export_mod_raw_noreturn.rs:22:5 --> $DIR/export_mod_raw_noreturn.rs:22:5

View File

@ -1,8 +1,8 @@
error: property getter requires exactly 1 parameter error: property getter requires exactly 1 parameter
--> $DIR/rhai_fn_getter_signature.rs:13:9 --> $DIR/rhai_fn_getter_signature.rs:13:20
| |
13 | pub fn test_fn(input: Point, value: bool) -> bool { 13 | pub fn test_fn(input: Point, value: bool) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared crate or module `test_module` error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
--> $DIR/rhai_fn_getter_signature.rs:23:8 --> $DIR/rhai_fn_getter_signature.rs:23:8

View File

@ -1,4 +1,4 @@
error: conflicting namespace error: namespace is already set to 'global'
--> $DIR/rhai_fn_global_multiple.rs:12:23 --> $DIR/rhai_fn_global_multiple.rs:12:23
| |
12 | #[rhai_fn(global, internal)] 12 | #[rhai_fn(global, internal)]

View File

@ -1,8 +1,8 @@
error: index getter requires exactly 2 parameters error: index getter requires exactly 2 parameters
--> $DIR/rhai_fn_index_getter_signature.rs:13:9 --> $DIR/rhai_fn_index_getter_signature.rs:13:20
| |
13 | pub fn test_fn(input: Point) -> bool { 13 | pub fn test_fn(input: Point) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared crate or module `test_module` error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
--> $DIR/rhai_fn_index_getter_signature.rs:23:8 --> $DIR/rhai_fn_index_getter_signature.rs:23:8

View File

@ -1,8 +1,8 @@
error: index setter requires exactly 3 parameters error: index setter requires exactly 3 parameters
--> $DIR/rhai_fn_setter_index_signature.rs:13:9 --> $DIR/rhai_fn_setter_index_signature.rs:13:20
| |
13 | pub fn test_fn(input: Point) -> bool { 13 | pub fn test_fn(input: Point) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared crate or module `test_module` error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
--> $DIR/rhai_fn_setter_index_signature.rs:23:8 --> $DIR/rhai_fn_setter_index_signature.rs:23:8

View File

@ -1,8 +1,8 @@
error: property setter cannot return any value error: property setter cannot return any value
--> $DIR/rhai_fn_setter_return.rs:13:9 --> $DIR/rhai_fn_setter_return.rs:13:51
| |
13 | pub fn test_fn(input: &mut Point, value: f32) -> bool { 13 | pub fn test_fn(input: &mut Point, value: f32) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^
error[E0433]: failed to resolve: use of undeclared crate or module `test_module` error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
--> $DIR/rhai_fn_setter_return.rs:24:8 --> $DIR/rhai_fn_setter_return.rs:24:8

View File

@ -1,8 +1,8 @@
error: property setter requires exactly 2 parameters error: property setter requires exactly 2 parameters
--> $DIR/rhai_fn_setter_signature.rs:13:9 --> $DIR/rhai_fn_setter_signature.rs:13:20
| |
13 | pub fn test_fn(input: Point) -> bool { 13 | pub fn test_fn(input: Point) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^
error[E0433]: failed to resolve: use of undeclared crate or module `test_module` error[E0433]: failed to resolve: use of undeclared crate or module `test_module`
--> $DIR/rhai_fn_setter_signature.rs:23:8 --> $DIR/rhai_fn_setter_signature.rs:23:8