From 8de095fa361e61b8087128b1e89f971b3a1eb986 Mon Sep 17 00:00:00 2001 From: J Henry Waugh Date: Thu, 27 Aug 2020 22:49:56 -0500 Subject: [PATCH] Improve diagnostics for non-clonable return types --- codegen/src/function.rs | 12 +++++--- .../ui_tests/rhai_fn_non_clonable_return.rs | 27 +++++++++++++++++ .../rhai_fn_non_clonable_return.stderr | 10 +++++++ .../ui_tests/rhai_mod_non_clonable_return.rs | 29 +++++++++++++++++++ 4 files changed, 74 insertions(+), 4 deletions(-) create mode 100644 codegen/ui_tests/rhai_fn_non_clonable_return.rs create mode 100644 codegen/ui_tests/rhai_fn_non_clonable_return.stderr create mode 100644 codegen/ui_tests/rhai_mod_non_clonable_return.rs diff --git a/codegen/src/function.rs b/codegen/src/function.rs index b02a657d..a8862d20 100644 --- a/codegen/src/function.rs +++ b/codegen/src/function.rs @@ -314,15 +314,17 @@ impl ExportedFn { }) .collect(); + let return_span = self.return_type().map(|r| r.span()) + .unwrap_or_else(|| proc_macro2::Span::call_site()); if !self.params.return_raw { - quote! { + quote_spanned! { return_span=> type EvalBox = Box; pub #dynamic_signature { Ok(Dynamic::from(super::#name(#(#arguments),*))) } } } else { - quote_spanned! { self.return_type().unwrap().span()=> + quote_spanned! { return_span=> type EvalBox = Box; pub #dynamic_signature { super::#name(#(#arguments),*) @@ -484,12 +486,14 @@ impl ExportedFn { // Handle "raw returns", aka cases where the result is a dynamic or an error. // // This allows skipping the Dynamic::from wrap. + let return_span = self.return_type().map(|r| r.span()) + .unwrap_or_else(|| proc_macro2::Span::call_site()); let return_expr = if !self.params.return_raw { - quote! { + quote_spanned! { return_span=> Ok(Dynamic::from(#sig_name(#(#unpack_exprs),*))) } } else { - quote_spanned! { self.return_type().unwrap().span()=> + quote_spanned! { return_span=> #sig_name(#(#unpack_exprs),*) } }; diff --git a/codegen/ui_tests/rhai_fn_non_clonable_return.rs b/codegen/ui_tests/rhai_fn_non_clonable_return.rs new file mode 100644 index 00000000..e2e2d788 --- /dev/null +++ b/codegen/ui_tests/rhai_fn_non_clonable_return.rs @@ -0,0 +1,27 @@ +use rhai::plugin::*; + +struct NonClonable { + a: f32, + b: u32, + c: char, + d: bool, +} + +#[export_fn] +pub fn test_fn(input: f32) -> NonClonable { + NonClonable { + a: input, + b: 10, + c: 'a', + d: true, + } +} + +fn main() { + let n = test_fn(20.0); + if n.c == 'a' { + println!("yes"); + } else { + println!("no"); + } +} diff --git a/codegen/ui_tests/rhai_fn_non_clonable_return.stderr b/codegen/ui_tests/rhai_fn_non_clonable_return.stderr new file mode 100644 index 00000000..6184fd24 --- /dev/null +++ b/codegen/ui_tests/rhai_fn_non_clonable_return.stderr @@ -0,0 +1,10 @@ +error[E0277]: the trait bound `NonClonable: std::clone::Clone` is not satisfied + --> $DIR/rhai_fn_non_clonable_return.rs:11:8 + | +11 | pub fn test_fn(input: f32) -> NonClonable { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::clone::Clone` is not implemented for `NonClonable` + | + ::: /home/cryptkeeper/Desktop/Software/ytdl-replacement/rhai/src/any.rs:537:30 + | +537 | pub fn from(value: T) -> Self { + | ----- required by this bound in `rhai::Dynamic::from` diff --git a/codegen/ui_tests/rhai_mod_non_clonable_return.rs b/codegen/ui_tests/rhai_mod_non_clonable_return.rs new file mode 100644 index 00000000..fe8f5fff --- /dev/null +++ b/codegen/ui_tests/rhai_mod_non_clonable_return.rs @@ -0,0 +1,29 @@ +use rhai::plugin::*; + +struct NonClonable { + a: f32, + b: u32, + c: char, + d: bool, +} + +#[export_module] +pub mod test_mod { + pub fn test_fn(input: f32) -> NonClonable { + NonClonable { + a: input, + b: 10, + c: 'a', + d: true, + } + } +} + +fn main() { + let n = test_mod::test_fn(20.0); + if n.c == 'a' { + println!("yes"); + } else { + println!("no"); + } +}