@@ -72,6 +72,7 @@ pub(super) fn lower(
7272 is_lowering_coroutine : false ,
7373 label_ribs : Vec :: new ( ) ,
7474 current_binding_owner : None ,
75+ awaitable_context : None ,
7576 }
7677 . collect ( params, body, is_async_fn)
7778}
@@ -100,6 +101,8 @@ struct ExprCollector<'a> {
100101 // resolution
101102 label_ribs : Vec < LabelRib > ,
102103 current_binding_owner : Option < ExprId > ,
104+
105+ awaitable_context : Option < Awaitable > ,
103106}
104107
105108#[ derive( Clone , Debug ) ]
@@ -135,6 +138,11 @@ impl RibKind {
135138 }
136139}
137140
141+ enum Awaitable {
142+ Yes ,
143+ No ( & ' static str ) ,
144+ }
145+
138146#[ derive( Debug , Default ) ]
139147struct BindingList {
140148 map : FxHashMap < Name , BindingId > ,
@@ -180,6 +188,18 @@ impl ExprCollector<'_> {
180188 body : Option < ast:: Expr > ,
181189 is_async_fn : bool ,
182190 ) -> ( Body , BodySourceMap ) {
191+ self . awaitable_context . replace ( if is_async_fn {
192+ Awaitable :: Yes
193+ } else {
194+ match self . owner {
195+ DefWithBodyId :: FunctionId ( ..) => Awaitable :: No ( "non-async function" ) ,
196+ DefWithBodyId :: StaticId ( ..) => Awaitable :: No ( "static" ) ,
197+ DefWithBodyId :: ConstId ( ..) | DefWithBodyId :: InTypeConstId ( ..) => {
198+ Awaitable :: No ( "constant" )
199+ }
200+ DefWithBodyId :: VariantId ( ..) => Awaitable :: No ( "enum variant" ) ,
201+ }
202+ } ) ;
183203 if let Some ( ( param_list, mut attr_enabled) ) = param_list {
184204 let mut params = vec ! [ ] ;
185205 if let Some ( self_param) =
@@ -280,31 +300,40 @@ impl ExprCollector<'_> {
280300 }
281301 Some ( ast:: BlockModifier :: Async ( _) ) => {
282302 self . with_label_rib ( RibKind :: Closure , |this| {
283- this. collect_block_ ( e, |id, statements, tail| Expr :: Async {
284- id,
285- statements,
286- tail,
303+ this. with_awaitable_block ( Awaitable :: Yes , |this| {
304+ this. collect_block_ ( e, |id, statements, tail| Expr :: Async {
305+ id,
306+ statements,
307+ tail,
308+ } )
287309 } )
288310 } )
289311 }
290312 Some ( ast:: BlockModifier :: Const ( _) ) => {
291313 self . with_label_rib ( RibKind :: Constant , |this| {
292- let ( result_expr_id, prev_binding_owner) =
293- this. initialize_binding_owner ( syntax_ptr) ;
294- let inner_expr = this. collect_block ( e) ;
295- let it = this. db . intern_anonymous_const ( ConstBlockLoc {
296- parent : this. owner ,
297- root : inner_expr,
298- } ) ;
299- this. body . exprs [ result_expr_id] = Expr :: Const ( it) ;
300- this. current_binding_owner = prev_binding_owner;
301- result_expr_id
314+ this. with_awaitable_block ( Awaitable :: No ( "constant block" ) , |this| {
315+ let ( result_expr_id, prev_binding_owner) =
316+ this. initialize_binding_owner ( syntax_ptr) ;
317+ let inner_expr = this. collect_block ( e) ;
318+ let it = this. db . intern_anonymous_const ( ConstBlockLoc {
319+ parent : this. owner ,
320+ root : inner_expr,
321+ } ) ;
322+ this. body . exprs [ result_expr_id] = Expr :: Const ( it) ;
323+ this. current_binding_owner = prev_binding_owner;
324+ result_expr_id
325+ } )
302326 } )
303327 }
304328 // FIXME
305- Some ( ast:: BlockModifier :: AsyncGen ( _) ) | Some ( ast :: BlockModifier :: Gen ( _ ) ) | None => {
306- self . collect_block ( e)
329+ Some ( ast:: BlockModifier :: AsyncGen ( _) ) => {
330+ self . with_awaitable_block ( Awaitable :: Yes , |this| this . collect_block ( e) )
307331 }
332+ Some ( ast:: BlockModifier :: Gen ( _) ) => self
333+ . with_awaitable_block ( Awaitable :: No ( "non-async gen block" ) , |this| {
334+ this. collect_block ( e)
335+ } ) ,
336+ None => self . collect_block ( e) ,
308337 } ,
309338 ast:: Expr :: LoopExpr ( e) => {
310339 let label = e. label ( ) . map ( |label| self . collect_label ( label) ) ;
@@ -469,6 +498,12 @@ impl ExprCollector<'_> {
469498 }
470499 ast:: Expr :: AwaitExpr ( e) => {
471500 let expr = self . collect_expr_opt ( e. expr ( ) ) ;
501+ if let Awaitable :: No ( location) = self . is_lowering_awaitable_block ( ) {
502+ self . source_map . diagnostics . push ( BodyDiagnostic :: AwaitOutsideOfAsync {
503+ node : InFile :: new ( self . expander . current_file_id ( ) , AstPtr :: new ( & e) ) ,
504+ location : location. to_string ( ) ,
505+ } ) ;
506+ }
472507 self . alloc_expr ( Expr :: Await { expr } , syntax_ptr)
473508 }
474509 ast:: Expr :: TryExpr ( e) => self . collect_try_operator ( syntax_ptr, e) ,
@@ -527,7 +562,13 @@ impl ExprCollector<'_> {
527562 let prev_is_lowering_coroutine = mem:: take ( & mut this. is_lowering_coroutine ) ;
528563 let prev_try_block_label = this. current_try_block_label . take ( ) ;
529564
530- let body = this. collect_expr_opt ( e. body ( ) ) ;
565+ let awaitable = if e. async_token ( ) . is_some ( ) {
566+ Awaitable :: Yes
567+ } else {
568+ Awaitable :: No ( "non-async closure" )
569+ } ;
570+ let body =
571+ this. with_awaitable_block ( awaitable, |this| this. collect_expr_opt ( e. body ( ) ) ) ;
531572
532573 let closure_kind = if this. is_lowering_coroutine {
533574 let movability = if e. static_token ( ) . is_some ( ) {
@@ -2082,6 +2123,21 @@ impl ExprCollector<'_> {
20822123 fn alloc_label_desugared ( & mut self , label : Label ) -> LabelId {
20832124 self . body . labels . alloc ( label)
20842125 }
2126+
2127+ fn is_lowering_awaitable_block ( & self ) -> & Awaitable {
2128+ self . awaitable_context . as_ref ( ) . unwrap_or ( & Awaitable :: No ( "unknown" ) )
2129+ }
2130+
2131+ fn with_awaitable_block < T > (
2132+ & mut self ,
2133+ awaitable : Awaitable ,
2134+ f : impl FnOnce ( & mut Self ) -> T ,
2135+ ) -> T {
2136+ let orig = self . awaitable_context . replace ( awaitable) ;
2137+ let res = f ( self ) ;
2138+ self . awaitable_context = orig;
2139+ res
2140+ }
20852141}
20862142
20872143fn comma_follows_token ( t : Option < syntax:: SyntaxToken > ) -> bool {
0 commit comments