@@ -296,6 +296,14 @@ enum AnonymousLifetimeMode {
296296 PassThrough ,
297297}
298298
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+
299307impl < ' a > LoweringContext < ' a > {
300308 fn lower_crate ( mut self , c : & Crate ) -> hir:: Crate {
301309 /// Full-crate AST visitor that inserts into a fresh
@@ -1050,7 +1058,7 @@ impl<'a> LoweringContext<'a> {
10501058 ) ,
10511059 unsafety : this. lower_unsafety ( f. unsafety ) ,
10521060 abi : f. abi ,
1053- decl : this. lower_fn_decl ( & f. decl , None , false ) ,
1061+ decl : this. lower_fn_decl ( & f. decl , None , false , & NonAsyncRet ) ,
10541062 arg_names : this. lower_fn_args_to_names ( & f. decl ) ,
10551063 } ) )
10561064 } ,
@@ -1729,7 +1737,121 @@ impl<'a> LoweringContext<'a> {
17291737 decl : & FnDecl ,
17301738 fn_def_id : Option < DefId > ,
17311739 impl_trait_return_allow : bool ,
1740+ fn_ret_transform : & FnRetTransform ,
17321741 ) -> 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+
17331855 // NOTE: The two last parameters here have to do with impl Trait. If fn_def_id is Some,
17341856 // then impl Trait arguments are lowered into generic parameters on the given
17351857 // fn_def_id, otherwise impl Trait is disallowed. (for now)
@@ -1748,15 +1870,7 @@ impl<'a> LoweringContext<'a> {
17481870 }
17491871 } )
17501872 . 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) ,
17601874 variadic : decl. variadic ,
17611875 has_implicit_self : decl. inputs . get ( 0 ) . map_or ( false , |arg| match arg. ty . node {
17621876 TyKind :: ImplicitSelf => true ,
@@ -2201,11 +2315,15 @@ impl<'a> LoweringContext<'a> {
22012315 let body = this. lower_block ( body, false ) ;
22022316 this. expr_block ( body, ThinVec :: new ( ) )
22032317 } ) ;
2318+ let fn_ret_transform: & FnRetTransform = match header. asyncness {
2319+ IsAsync :: Async => & AsyncFunctionRet ,
2320+ IsAsync :: NotAsync => & NonAsyncRet ,
2321+ } ;
22042322 let ( generics, fn_decl) = this. add_in_band_defs (
22052323 generics,
22062324 fn_def_id,
22072325 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 ) ,
22092327 ) ;
22102328
22112329 hir:: ItemFn (
@@ -2721,7 +2839,7 @@ impl<'a> LoweringContext<'a> {
27212839 |this| {
27222840 (
27232841 // Disallow impl Trait in foreign items
2724- this. lower_fn_decl ( fdec, None , false ) ,
2842+ this. lower_fn_decl ( fdec, None , false , & NonAsyncRet ) ,
27252843 this. lower_fn_args_to_names ( fdec) ,
27262844 )
27272845 } ,
@@ -2747,9 +2865,13 @@ impl<'a> LoweringContext<'a> {
27472865 fn_def_id : DefId ,
27482866 impl_trait_return_allow : bool ,
27492867 ) -> hir:: MethodSig {
2868+ let fn_ret_transform: & FnRetTransform = match sig. header . asyncness {
2869+ IsAsync :: Async => & AsyncFunctionRet ,
2870+ IsAsync :: NotAsync => & NonAsyncRet ,
2871+ } ;
27502872 hir:: MethodSig {
27512873 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 ) ,
27532875 }
27542876 }
27552877
@@ -3074,7 +3196,7 @@ impl<'a> LoweringContext<'a> {
30743196 arms. iter ( ) . map ( |x| self . lower_arm ( x) ) . collect ( ) ,
30753197 hir:: MatchSource :: Normal ,
30763198 ) ,
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) => {
30783200 self . with_new_scopes ( |this| {
30793201 this. with_parent_def ( e. id , |this| {
30803202 let mut is_generator = false ;
@@ -3108,9 +3230,13 @@ impl<'a> LoweringContext<'a> {
31083230 }
31093231 None
31103232 } ;
3233+ let fn_ret_transform: & FnRetTransform = match asyncness {
3234+ IsAsync :: Async => & AsyncClosureRet ,
3235+ IsAsync :: NotAsync => & NonAsyncRet ,
3236+ } ;
31113237 hir:: ExprClosure (
31123238 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 ) ,
31143240 body_id,
31153241 fn_decl_span,
31163242 generator_option,
0 commit comments