@@ -296,6 +296,14 @@ enum AnonymousLifetimeMode {
296
296
PassThrough ,
297
297
}
298
298
299
+ trait FnRetTransform {
300
+ fn lower ( & self , ctx : & mut LoweringContext , output : & FunctionRetTy , impl_trait_context : ImplTraitContext ) -> hir:: FunctionRetTy ;
301
+ }
302
+
303
+ struct NonAsyncRet ;
304
+ struct AsyncClosureRet ;
305
+ struct AsyncFunctionRet ;
306
+
299
307
impl < ' a > LoweringContext < ' a > {
300
308
fn lower_crate ( mut self , c : & Crate ) -> hir:: Crate {
301
309
/// Full-crate AST visitor that inserts into a fresh
@@ -1050,7 +1058,7 @@ impl<'a> LoweringContext<'a> {
1050
1058
) ,
1051
1059
unsafety : this. lower_unsafety ( f. unsafety ) ,
1052
1060
abi : f. abi ,
1053
- decl : this. lower_fn_decl ( & f. decl , None , false ) ,
1061
+ decl : this. lower_fn_decl ( & f. decl , None , false , & NonAsyncRet ) ,
1054
1062
arg_names : this. lower_fn_args_to_names ( & f. decl ) ,
1055
1063
} ) )
1056
1064
} ,
@@ -1729,7 +1737,121 @@ impl<'a> LoweringContext<'a> {
1729
1737
decl : & FnDecl ,
1730
1738
fn_def_id : Option < DefId > ,
1731
1739
impl_trait_return_allow : bool ,
1740
+ fn_ret_transform : & FnRetTransform ,
1732
1741
) -> P < hir:: FnDecl > {
1742
+ // For non async functions, the return type is lowered in a straightforward way
1743
+ impl FnRetTransform for NonAsyncRet {
1744
+ fn lower ( & self , ctx : & mut LoweringContext , output : & FunctionRetTy , impl_trait_context : ImplTraitContext ) -> hir:: FunctionRetTy {
1745
+ match output {
1746
+ FunctionRetTy :: Ty ( ty) => hir:: Return ( ctx. lower_ty ( ty, impl_trait_context) ) ,
1747
+ FunctionRetTy :: Default ( span) => hir:: DefaultReturn ( * span) ,
1748
+ }
1749
+ }
1750
+ }
1751
+
1752
+ // For async closures:
1753
+ // - If the return type is omitted, a straightforward lowering is performed
1754
+ // - If the return type is explicit, given a return type T, it is lowered to
1755
+ // ::std::raw::GenFuture<_, T>
1756
+ impl FnRetTransform for AsyncClosureRet {
1757
+ fn lower ( & self , ctx : & mut LoweringContext , output : & FunctionRetTy , impl_trait_context : ImplTraitContext ) -> hir:: FunctionRetTy {
1758
+ match output {
1759
+ FunctionRetTy :: Ty ( ty) => {
1760
+ let inner_ty = ctx. lower_ty ( ty, impl_trait_context) ;
1761
+ let span = inner_ty. span ;
1762
+ let hir:: Path { def, segments, .. } = ctx. std_path ( span, & [ "raw" , "GenFuture" ] , false ) ;
1763
+ let LoweredNodeId { node_id, hir_id } = ctx. next_id ( ) ;
1764
+ let gen_future_path = hir:: Path {
1765
+ segments : segments. map_slice ( |mut v| {
1766
+ v. last_mut ( ) . unwrap ( ) . parameters = Some ( P ( hir:: PathParameters {
1767
+ lifetimes : hir_vec ! [ ] ,
1768
+ bindings : hir_vec ! [ ] ,
1769
+ types : hir_vec ! [
1770
+ P ( hir:: Ty {
1771
+ id: node_id,
1772
+ node: hir:: TyInfer ,
1773
+ hir_id, span,
1774
+ } ) ,
1775
+ inner_ty,
1776
+ ] ,
1777
+ parenthesized : false ,
1778
+ } ) ) ;
1779
+ v
1780
+ } ) ,
1781
+ def, span
1782
+ } ;
1783
+
1784
+ let LoweredNodeId { node_id, hir_id } = ctx. next_id ( ) ;
1785
+ hir:: Return ( P ( hir:: Ty {
1786
+ id : node_id,
1787
+ node : hir:: TyPath ( hir:: QPath :: Resolved ( None , P ( gen_future_path) ) ) ,
1788
+ hir_id, span,
1789
+ } ) )
1790
+ }
1791
+ FunctionRetTy :: Default ( span) => hir:: DefaultReturn ( * span) ,
1792
+ }
1793
+ }
1794
+ }
1795
+
1796
+ // For async functions the return type is lowered to impl ::std::future::Future<Output = T>
1797
+ impl FnRetTransform for AsyncFunctionRet {
1798
+ fn lower ( & self , ctx : & mut LoweringContext , output : & FunctionRetTy , impl_trait_context : ImplTraitContext ) -> hir:: FunctionRetTy {
1799
+ let inner_ty = match output {
1800
+ FunctionRetTy :: Ty ( ty) => ctx. lower_ty ( ty, impl_trait_context) ,
1801
+ FunctionRetTy :: Default ( span) => {
1802
+ let LoweredNodeId { node_id, hir_id } = ctx. next_id ( ) ;
1803
+ P ( hir:: Ty {
1804
+ id : node_id,
1805
+ hir_id : hir_id,
1806
+ node : hir:: TyTup ( hir_vec ! [ ] ) ,
1807
+ span : * span,
1808
+ } )
1809
+ }
1810
+ } ;
1811
+ let span = inner_ty. span ;
1812
+ let hir:: Path { def, segments, .. } = ctx. std_path ( span, & [ "future" , "Future" ] , false ) ;
1813
+ let future_path = hir:: Path {
1814
+ segments : segments. map_slice ( |mut v| {
1815
+ v. last_mut ( ) . unwrap ( ) . parameters = Some ( P ( hir:: PathParameters {
1816
+ lifetimes : hir_vec ! [ ] ,
1817
+ types : hir_vec ! [ ] ,
1818
+ bindings : hir_vec ! [ hir:: TypeBinding {
1819
+ name: ctx. str_to_ident( "Output" ) ,
1820
+ ty: inner_ty,
1821
+ id: ctx. next_id( ) . node_id,
1822
+ span,
1823
+ } ] ,
1824
+ parenthesized : false ,
1825
+ } ) ) ;
1826
+ v
1827
+ } ) ,
1828
+ def, span
1829
+ } ;
1830
+ let LoweredNodeId { hir_id, node_id } = ctx. next_id ( ) ;
1831
+ hir:: Return ( P ( hir:: Ty {
1832
+ id : node_id,
1833
+ node : hir:: TyImplTraitExistential ( hir:: ExistTy {
1834
+ generics : hir:: Generics :: empty ( ) ,
1835
+ bounds : hir_vec ! [ hir:: TyParamBound :: TraitTyParamBound ( hir:: PolyTraitRef {
1836
+ trait_ref: hir:: TraitRef {
1837
+ path: future_path,
1838
+ ref_id: ctx. next_id( ) . node_id,
1839
+ } ,
1840
+ bound_generic_params: hir_vec![ ] ,
1841
+ span,
1842
+ } , hir:: TraitBoundModifier :: None ) ] ,
1843
+ } , hir_vec ! [ ] ) ,
1844
+ hir_id, span,
1845
+ } ) )
1846
+ }
1847
+ }
1848
+
1849
+ let output_impl_trait_context = if fn_def_id. is_some ( ) && impl_trait_return_allow {
1850
+ ImplTraitContext :: Existential
1851
+ } else {
1852
+ ImplTraitContext :: Disallowed
1853
+ } ;
1854
+
1733
1855
// NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some,
1734
1856
// then impl Trait arguments are lowered into generic parameters on the given
1735
1857
// fn_def_id, otherwise impl Trait is disallowed. (for now)
@@ -1748,15 +1870,7 @@ impl<'a> LoweringContext<'a> {
1748
1870
}
1749
1871
} )
1750
1872
. collect ( ) ,
1751
- output : match decl. output {
1752
- FunctionRetTy :: Ty ( ref ty) => match fn_def_id {
1753
- Some ( _) if impl_trait_return_allow => {
1754
- hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Existential ) )
1755
- }
1756
- _ => hir:: Return ( self . lower_ty ( ty, ImplTraitContext :: Disallowed ) ) ,
1757
- } ,
1758
- FunctionRetTy :: Default ( span) => hir:: DefaultReturn ( span) ,
1759
- } ,
1873
+ output : fn_ret_transform. lower ( self , & decl. output , output_impl_trait_context) ,
1760
1874
variadic : decl. variadic ,
1761
1875
has_implicit_self : decl. inputs . get ( 0 ) . map_or ( false , |arg| match arg. ty . node {
1762
1876
TyKind :: ImplicitSelf => true ,
@@ -2201,11 +2315,15 @@ impl<'a> LoweringContext<'a> {
2201
2315
let body = this. lower_block ( body, false ) ;
2202
2316
this. expr_block ( body, ThinVec :: new ( ) )
2203
2317
} ) ;
2318
+ let fn_ret_transform: & FnRetTransform = match header. asyncness {
2319
+ IsAsync :: Async => & AsyncFunctionRet ,
2320
+ IsAsync :: NotAsync => & NonAsyncRet ,
2321
+ } ;
2204
2322
let ( generics, fn_decl) = this. add_in_band_defs (
2205
2323
generics,
2206
2324
fn_def_id,
2207
2325
AnonymousLifetimeMode :: PassThrough ,
2208
- |this| this. lower_fn_decl ( decl, Some ( fn_def_id) , true ) ,
2326
+ |this| this. lower_fn_decl ( decl, Some ( fn_def_id) , true , fn_ret_transform ) ,
2209
2327
) ;
2210
2328
2211
2329
hir:: ItemFn (
@@ -2721,7 +2839,7 @@ impl<'a> LoweringContext<'a> {
2721
2839
|this| {
2722
2840
(
2723
2841
// Disallow impl Trait in foreign items
2724
- this. lower_fn_decl ( fdec, None , false ) ,
2842
+ this. lower_fn_decl ( fdec, None , false , & NonAsyncRet ) ,
2725
2843
this. lower_fn_args_to_names ( fdec) ,
2726
2844
)
2727
2845
} ,
@@ -2747,9 +2865,13 @@ impl<'a> LoweringContext<'a> {
2747
2865
fn_def_id : DefId ,
2748
2866
impl_trait_return_allow : bool ,
2749
2867
) -> hir:: MethodSig {
2868
+ let fn_ret_transform: & FnRetTransform = match sig. header . asyncness {
2869
+ IsAsync :: Async => & AsyncFunctionRet ,
2870
+ IsAsync :: NotAsync => & NonAsyncRet ,
2871
+ } ;
2750
2872
hir:: MethodSig {
2751
2873
header : self . lower_fn_header ( sig. header ) ,
2752
- decl : self . lower_fn_decl ( & sig. decl , Some ( fn_def_id) , impl_trait_return_allow) ,
2874
+ decl : self . lower_fn_decl ( & sig. decl , Some ( fn_def_id) , impl_trait_return_allow, fn_ret_transform ) ,
2753
2875
}
2754
2876
}
2755
2877
@@ -3074,7 +3196,7 @@ impl<'a> LoweringContext<'a> {
3074
3196
arms. iter ( ) . map ( |x| self . lower_arm ( x) ) . collect ( ) ,
3075
3197
hir:: MatchSource :: Normal ,
3076
3198
) ,
3077
- ExprKind :: Closure ( capture_clause, movability, ref decl, ref body, fn_decl_span) => {
3199
+ ExprKind :: Closure ( capture_clause, asyncness , movability, ref decl, ref body, fn_decl_span) => {
3078
3200
self . with_new_scopes ( |this| {
3079
3201
this. with_parent_def ( e. id , |this| {
3080
3202
let mut is_generator = false ;
@@ -3108,9 +3230,13 @@ impl<'a> LoweringContext<'a> {
3108
3230
}
3109
3231
None
3110
3232
} ;
3233
+ let fn_ret_transform: & FnRetTransform = match asyncness {
3234
+ IsAsync :: Async => & AsyncClosureRet ,
3235
+ IsAsync :: NotAsync => & NonAsyncRet ,
3236
+ } ;
3111
3237
hir:: ExprClosure (
3112
3238
this. lower_capture_clause ( capture_clause) ,
3113
- this. lower_fn_decl ( decl, None , false ) ,
3239
+ this. lower_fn_decl ( decl, None , false , fn_ret_transform ) ,
3114
3240
body_id,
3115
3241
fn_decl_span,
3116
3242
generator_option,
0 commit comments