From 9317aa4a7a1a683927153be1a00cf23aa2406f13 Mon Sep 17 00:00:00 2001 From: Yusuke Sasaki Date: Sat, 18 Apr 2020 21:55:30 +0900 Subject: [PATCH] bind the value of tail expr before Ok-wrarpping It changes the desugaring rule to bind the return value to a temporary variable before wrapping, rather than modifying the AST of tail expression. --- fehler-macros/src/throws.rs | 56 ++++++++++--------------------------- 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/fehler-macros/src/throws.rs b/fehler-macros/src/throws.rs index 0121737..200f7bb 100644 --- a/fehler-macros/src/throws.rs +++ b/fehler-macros/src/throws.rs @@ -37,35 +37,33 @@ impl Throws { } impl Fold for Throws { - fn fold_item_fn(&mut self, mut i: syn::ItemFn) -> syn::ItemFn { + fn fold_item_fn(&mut self, i: syn::ItemFn) -> syn::ItemFn { if !self.outer_fn { return i; } self.outer_fn = false; - modify_tail(is_unit_fn(&i.sig.output), &mut i.block.stmts); - let sig = syn::Signature { output: self.fold_return_type(i.sig.output), ..i.sig }; - let block = Box::new(self.fold_block(*i.block)); + let inner = self.fold_block(*i.block); + let block = Box::new(make_fn_block(&inner)); syn::ItemFn { sig, block, ..i } } - fn fold_impl_item_method(&mut self, mut i: syn::ImplItemMethod) -> syn::ImplItemMethod { + fn fold_impl_item_method(&mut self, i: syn::ImplItemMethod) -> syn::ImplItemMethod { if !self.outer_fn { return i; } self.outer_fn = false; - modify_tail(is_unit_fn(&i.sig.output), &mut i.block.stmts); - let sig = syn::Signature { output: self.fold_return_type(i.sig.output), ..i.sig }; - let block = self.fold_block(i.block); + let inner = self.fold_block(i.block); + let block = make_fn_block(&inner); syn::ImplItemMethod { sig, block, ..i } } @@ -74,9 +72,9 @@ impl Fold for Throws { if !self.outer_fn { return i; } self.outer_fn = false; - let default = i.default.take().map(|mut block| { - modify_tail(is_unit_fn(&i.sig.output), &mut block.stmts); - self.fold_block(block) + let default = i.default.take().map(|block| { + let inner = self.fold_block(block); + make_fn_block(&inner) }); let sig = syn::Signature { @@ -108,37 +106,13 @@ impl Fold for Throws { } } -fn modify_tail(is_unit_fn: bool, stmts: &mut Vec) { - let last_non_item_stmt = stmts.iter_mut().rev().filter(|s| { - if let syn::Stmt::Item(_) = s { false } else { true } - }).next(); - match last_non_item_stmt { - Some(syn::Stmt::Expr(e)) if is_unit_fn => { - let new = syn::parse2(quote::quote!(#e;)).unwrap(); - stmts.pop(); - stmts.push(new); - stmts.push(syn::Stmt::Expr(ok_unit())); - } - Some(syn::Stmt::Expr(e)) => { - *e = ok(e); - } - _ if is_unit_fn => { - stmts.push(syn::Stmt::Expr(ok_unit())); - } - _ => { } - } -} - +fn make_fn_block(inner: &syn::Block) -> syn::Block { + syn::parse2(quote::quote! {{ + let __ret = #inner; -fn is_unit_fn(i: &syn::ReturnType) -> bool { - match i { - syn::ReturnType::Default => true, - syn::ReturnType::Type(_, ty) => { - if let syn::Type::Tuple(syn::TypeTuple { elems, .. }) = &**ty { - elems.is_empty() - } else { false } - } - } + #[allow(unreachable_code)] + <_ as ::fehler::__internal::_Succeed>::from_ok(__ret) + }}).unwrap() } fn ok(expr: &syn::Expr) -> syn::Expr {