Improve diagonstics on return_raw return mismatches

This commit is contained in:
J Henry Waugh 2020-08-23 17:22:29 -05:00
parent 7c273e0aac
commit 3fd3da6bfc
6 changed files with 104 additions and 9 deletions

View File

@ -2,6 +2,8 @@
#[cfg(no_std)]
use core::mem;
#[cfg(not(no_std))]
use std::mem;
#[cfg(no_std)]
use alloc::format;
@ -291,12 +293,21 @@ impl ExportedFn {
}
}
pub fn generate_with_params(
mut self,
mut params: ExportedFnParams,
) -> proc_macro2::TokenStream {
pub fn set_params(
&mut self, mut params: ExportedFnParams,
) -> syn::Result<()> {
// Do not allow non-returning raw functions.
//
// This is caught now to avoid issues with diagnostics later.
if params.return_raw && mem::discriminant(&self.signature.output) ==
mem::discriminant(&syn::ReturnType::Default) {
return Err(syn::Error::new(self.signature.span(),
"return_raw functions must return Result<T>"));
}
self.params = params;
self.generate()
Ok(())
}
pub fn generate(self) -> proc_macro2::TokenStream {
@ -353,7 +364,7 @@ impl ExportedFn {
}
}
} else {
quote! {
quote_spanned! { self.return_type().unwrap().span()=>
type EvalBox = Box<EvalAltResult>;
pub #dynamic_signature {
super::#name(#(#arguments),*)
@ -520,7 +531,7 @@ impl ExportedFn {
Ok(Dynamic::from(#sig_name(#(#unpack_exprs),*)))
}
} else {
quote! {
quote_spanned! { self.return_type().unwrap().span()=>
#sig_name(#(#unpack_exprs),*)
}
};

View File

@ -109,9 +109,12 @@ pub fn export_fn(
let mut output = proc_macro2::TokenStream::from(input.clone());
let parsed_params = parse_macro_input!(args as function::ExportedFnParams);
let function_def = parse_macro_input!(input as function::ExportedFn);
let mut function_def = parse_macro_input!(input as function::ExportedFn);
if let Err(e) = function_def.set_params(parsed_params) {
return e.to_compile_error().into();
}
output.extend(function_def.generate_with_params(parsed_params));
output.extend(function_def.generate());
proc_macro::TokenStream::from(output)
}

View File

@ -0,0 +1,25 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(return_raw)]
pub fn test_fn(input: &mut Point) {
input.x += 1.0;
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
test_fn(&mut n);
if n.x >= 10.0 {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,11 @@
error: return_raw functions must return Result<T>
--> $DIR/export_fn_raw_noreturn.rs:10:5
|
10 | pub fn test_fn(input: &mut Point) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error[E0425]: cannot find function `test_fn` in this scope
--> $DIR/export_fn_raw_noreturn.rs:19:5
|
19 | test_fn(&mut n);
| ^^^^^^^ not found in this scope

View File

@ -0,0 +1,24 @@
use rhai::plugin::*;
#[derive(Clone)]
struct Point {
x: f32,
y: f32,
}
#[export_fn(return_raw)]
pub fn test_fn(input: Point) -> bool {
input.x > input.y
}
fn main() {
let n = Point {
x: 0.0,
y: 10.0,
};
if test_fn(n) {
println!("yes");
} else {
println!("no");
}
}

View File

@ -0,0 +1,21 @@
error[E0308]: mismatched types
--> $DIR/export_fn_raw_return.rs:10:8
|
9 | #[export_fn(return_raw)]
| ------------------------ expected `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>` because of return type
10 | pub fn test_fn(input: Point) -> bool {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `std::result::Result`, found `bool`
|
= note: expected enum `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>`
found type `bool`
error[E0308]: mismatched types
--> $DIR/export_fn_raw_return.rs:10:33
|
9 | #[export_fn(return_raw)]
| ------------------------ expected `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>` because of return type
10 | pub fn test_fn(input: Point) -> bool {
| ^^^^ expected enum `std::result::Result`, found `bool`
|
= note: expected enum `std::result::Result<rhai::Dynamic, std::boxed::Box<rhai::EvalAltResult>>`
found type `bool`