Skip to content

Commit df2e3d4

Browse files
ubnt-intrepidwithoutboats
authored andcommitted
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.
1 parent 67a2373 commit df2e3d4

File tree

1 file changed

+15
-41
lines changed

1 file changed

+15
-41
lines changed

fehler-macros/src/throws.rs

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -37,35 +37,33 @@ impl Throws {
3737
}
3838

3939
impl Fold for Throws {
40-
fn fold_item_fn(&mut self, mut i: syn::ItemFn) -> syn::ItemFn {
40+
fn fold_item_fn(&mut self, i: syn::ItemFn) -> syn::ItemFn {
4141
if !self.outer_fn { return i; }
4242
self.outer_fn = false;
4343

44-
modify_tail(is_unit_fn(&i.sig.output), &mut i.block.stmts);
45-
4644
let sig = syn::Signature {
4745
output: self.fold_return_type(i.sig.output),
4846
..i.sig
4947
};
5048

5149

52-
let block = Box::new(self.fold_block(*i.block));
50+
let inner = self.fold_block(*i.block);
51+
let block = Box::new(make_fn_block(&inner));
5352

5453
syn::ItemFn { sig, block, ..i }
5554
}
5655

57-
fn fold_impl_item_method(&mut self, mut i: syn::ImplItemMethod) -> syn::ImplItemMethod {
56+
fn fold_impl_item_method(&mut self, i: syn::ImplItemMethod) -> syn::ImplItemMethod {
5857
if !self.outer_fn { return i; }
5958
self.outer_fn = false;
6059

61-
modify_tail(is_unit_fn(&i.sig.output), &mut i.block.stmts);
62-
6360
let sig = syn::Signature {
6461
output: self.fold_return_type(i.sig.output),
6562
..i.sig
6663
};
6764

68-
let block = self.fold_block(i.block);
65+
let inner = self.fold_block(i.block);
66+
let block = make_fn_block(&inner);
6967

7068
syn::ImplItemMethod { sig, block, ..i }
7169
}
@@ -74,9 +72,9 @@ impl Fold for Throws {
7472
if !self.outer_fn { return i; }
7573
self.outer_fn = false;
7674

77-
let default = i.default.take().map(|mut block| {
78-
modify_tail(is_unit_fn(&i.sig.output), &mut block.stmts);
79-
self.fold_block(block)
75+
let default = i.default.take().map(|block| {
76+
let inner = self.fold_block(block);
77+
make_fn_block(&inner)
8078
});
8179

8280
let sig = syn::Signature {
@@ -108,37 +106,13 @@ impl Fold for Throws {
108106
}
109107
}
110108

111-
fn modify_tail(is_unit_fn: bool, stmts: &mut Vec<syn::Stmt>) {
112-
let last_non_item_stmt = stmts.iter_mut().rev().filter(|s| {
113-
if let syn::Stmt::Item(_) = s { false } else { true }
114-
}).next();
115-
match last_non_item_stmt {
116-
Some(syn::Stmt::Expr(e)) if is_unit_fn => {
117-
let new = syn::parse2(quote::quote!(#e;)).unwrap();
118-
stmts.pop();
119-
stmts.push(new);
120-
stmts.push(syn::Stmt::Expr(ok_unit()));
121-
}
122-
Some(syn::Stmt::Expr(e)) => {
123-
*e = ok(e);
124-
}
125-
_ if is_unit_fn => {
126-
stmts.push(syn::Stmt::Expr(ok_unit()));
127-
}
128-
_ => { }
129-
}
130-
}
131-
109+
fn make_fn_block(inner: &syn::Block) -> syn::Block {
110+
syn::parse2(quote::quote! {{
111+
let __ret = #inner;
132112

133-
fn is_unit_fn(i: &syn::ReturnType) -> bool {
134-
match i {
135-
syn::ReturnType::Default => true,
136-
syn::ReturnType::Type(_, ty) => {
137-
if let syn::Type::Tuple(syn::TypeTuple { elems, .. }) = &**ty {
138-
elems.is_empty()
139-
} else { false }
140-
}
141-
}
113+
#[allow(unreachable_code)]
114+
<_ as ::fehler::__internal::_Succeed>::from_ok(__ret)
115+
}}).unwrap()
142116
}
143117

144118
fn ok(expr: &syn::Expr) -> syn::Expr {

0 commit comments

Comments
 (0)