1
1
use proc_macro2:: { Span , TokenStream , TokenTree } ;
2
2
use quote:: { quote, quote_spanned, ToTokens } ;
3
3
use syn:: parse:: { Parse , ParseStream , Parser } ;
4
- use syn:: { braced, Attribute , Ident , Path , Signature , Visibility } ;
4
+ use syn:: { braced, parse_quote , Attribute , Ident , Path , Signature , Visibility } ;
5
5
6
6
// syn::AttributeArgs does not implement syn::Parse
7
7
type AttributeArgs = syn:: punctuated:: Punctuated < syn:: Meta , syn:: Token ![ , ] > ;
@@ -380,24 +380,39 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
380
380
}
381
381
} ;
382
382
383
+ let unit_type = Box :: new ( parse_quote ! { ( ) } ) ;
384
+ let never_type = Box :: new ( parse_quote ! { ! } ) ;
385
+
383
386
let output_type = match & input. sig . output {
384
387
// For functions with no return value syn doesn't print anything,
385
388
// but that doesn't work as `Output` for our boxed `Future`, so
386
389
// default to `()` (the same type as the function output).
387
- syn:: ReturnType :: Default => quote ! { ( ) } ,
388
- syn:: ReturnType :: Type ( _, ret_type) => quote ! { #ret_type } ,
390
+ syn:: ReturnType :: Default => & unit_type,
391
+ // match on never type
392
+ syn:: ReturnType :: Type ( _, ret_type) if ret_type == & never_type => & unit_type,
393
+ syn:: ReturnType :: Type ( _, ret_type) => ret_type,
389
394
} ;
390
395
391
- input. stmts . last_mut ( ) . map ( |stmt| {
392
- * stmt = quote ! {
393
- let _lst_stmt: #output_type = {
394
- #stmt
395
- } ;
396
- _lst_stmt
397
- } ;
398
- } ) ;
396
+ // input.stmts.last_mut().map(|stmt| {
397
+ // if output_type != &unit_type {
398
+ // *stmt = quote! {
399
+ // let _lst_stmt: #output_type = {
400
+ // #stmt
401
+ // };
402
+ // _lst_stmt
403
+ // };
404
+ // }
405
+ // });
399
406
400
407
let body = input. body ( ) ;
408
+ let body = if output_type == & unit_type {
409
+ quote ! { #body }
410
+ } else {
411
+ quote ! {
412
+ let main_body: #output_type = #body;
413
+ main_body
414
+ }
415
+ } ;
401
416
402
417
// For test functions pin the body to the stack and use `Pin<&mut dyn
403
418
// Future>` to reduce the amount of `Runtime::block_on` (and related
@@ -410,13 +425,13 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
410
425
// there will be no benefit.
411
426
let body = if is_test {
412
427
quote ! {
413
- let body = async #body;
428
+ let body = async { #body } ;
414
429
#crate_path:: pin!( body) ;
415
430
let body: :: core:: pin:: Pin <& mut dyn :: core:: future:: Future <Output = #output_type>> = body;
416
431
}
417
432
} else {
418
433
quote ! {
419
- let body = async #body;
434
+ let body = async { #body } ;
420
435
}
421
436
} ;
422
437
0 commit comments